diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 771e2fb953..fc19f4f3a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ permissions: write-all jobs: build: - name: ${{ matrix.config.variant }} ${{ matrix.config.target }} + name: ${{ matrix.config.variant }} ${{ matrix.config.target }} ${{ matrix.config.v8_enable_pointer_compression && 'ptrcomp' || '' }} runs-on: ${{ matrix.config.os }} timeout-minutes: 180 strategy: @@ -30,58 +30,82 @@ jobs: - os: macos-13 target: x86_64-apple-darwin variant: debug + v8_enable_pointer_compression: false cargo: cargo - os: macos-13 target: x86_64-apple-darwin variant: release + v8_enable_pointer_compression: false cargo: cargo - os: macos-14 target: aarch64-apple-darwin variant: asan + v8_enable_pointer_compression: false cargo: cargo - os: macos-14 target: aarch64-apple-darwin variant: debug + v8_enable_pointer_compression: false cargo: cargo - os: macos-14 target: aarch64-apple-darwin variant: release + v8_enable_pointer_compression: false cargo: cargo - os: ${{ github.repository == 'denoland/rusty_v8' && 'ubuntu-22.04-xl' || 'ubuntu-22.04' }} target: x86_64-unknown-linux-gnu variant: debug + v8_enable_pointer_compression: false cargo: cargo - os: ${{ github.repository == 'denoland/rusty_v8' && 'ubuntu-22.04-xl' || 'ubuntu-22.04' }} target: x86_64-unknown-linux-gnu variant: release + v8_enable_pointer_compression: false + cargo: cargo + + - os: ${{ github.repository == 'denoland/rusty_v8' && 'ubuntu-22.04-xl' || 'ubuntu-22.04' }} + target: x86_64-unknown-linux-gnu + variant: debug + v8_enable_pointer_compression: true + cargo: cargo + + - os: ${{ github.repository == 'denoland/rusty_v8' && 'ubuntu-22.04-xl' || 'ubuntu-22.04' }} + target: x86_64-unknown-linux-gnu + variant: release + v8_enable_pointer_compression: true cargo: cargo - os: ${{ github.repository == 'denoland/rusty_v8' && 'windows-2022-xxl' || 'windows-2022' }} target: x86_64-pc-windows-msvc variant: release # Note: we do not support windows debug builds. + v8_enable_pointer_compression: false cargo: cargo - os: ${{ github.repository == 'denoland/rusty_v8' && 'ubuntu-22.04-xl' || 'ubuntu-22.04' }} target: aarch64-unknown-linux-gnu variant: debug + v8_enable_pointer_compression: false cargo: cargo - os: ${{ github.repository == 'denoland/rusty_v8' && 'ubuntu-22.04-xl' || 'ubuntu-22.04' }} target: aarch64-unknown-linux-gnu variant: release + v8_enable_pointer_compression: false cargo: cargo env: V8_FROM_SOURCE: true CARGO_VARIANT_FLAG: ${{ matrix.config.variant == 'release' && '--release' || '' }} + CARGO_FEATURE_FLAGS: ${{ matrix.config.v8_enable_pointer_compression && '--features v8_enable_pointer_compression' || '' }} LIB_NAME: ${{ contains(matrix.config.target, 'windows') && 'rusty_v8' || 'librusty_v8' }} LIB_EXT: ${{ contains(matrix.config.target, 'windows') && 'lib' || 'a' }} + FEATURES_SUFFIX: ${{ matrix.config.v8_enable_pointer_compression && '_ptrcomp' || '' }} RUSTFLAGS: -D warnings steps: @@ -97,6 +121,12 @@ jobs: - name: Install rust uses: dsherret/rust-toolchain-file@v1 + - name: Install cargo-binstall + uses: cargo-bins/cargo-binstall@main + + - name: Install nextest + run: cargo binstall cargo-nextest --secure + - name: Install python uses: actions/setup-python@v5 with: @@ -137,10 +167,8 @@ jobs: target/*/.* target/*/build target/*/deps - key: - cargo-${{ matrix.config.target }}-${{ matrix.config.variant }}-${{ hashFiles('Cargo.lock', 'build.rs', 'git_submodule_status.txt') }} - restore-keys: - cargo-${{ matrix.config.target }}-${{ matrix.config.variant }}- + key: cargo-${{ matrix.config.target }}-${{ matrix.config.variant }}-{{ matrix.config.v8_enable_pointer_compression }}-${{ hashFiles('Cargo.lock', 'build.rs', 'git_submodule_status.txt') }} + restore-keys: cargo-${{ matrix.config.target }}-${{ matrix.config.variant }}-{{ matrix.config.v8_enable_pointer_compression }}- - name: Install and start sccache shell: pwsh @@ -195,29 +223,25 @@ jobs: # Is there a better way to install this tool? curl -O http://commondatastorage.googleapis.com/chromium-browser-clang-staging/Mac/dsymutil-llvmorg-17-init-19076-g5533fc10-1.tgz tar -C tools/clang/dsymutil/ -xvzf dsymutil-llvmorg-17-init-19076-g5533fc10-1.tgz - V8_FROM_SOURCE=true RUSTFLAGS="-C opt-level=1 -Zsanitizer=address" cargo +nightly -Z build-std test --lib --bins --tests -vv --target ${{ matrix.config.target }} + V8_FROM_SOURCE=true RUSTFLAGS="-C opt-level=1 -Zsanitizer=address" cargo +nightly -Z build-std nextest run --lib --bins --tests -v --cargo-verbose --cargo-verbose --target ${{ matrix.config.target }} - name: Test env: SCCACHE_IDLE_TIMEOUT: 0 if: matrix.config.variant == 'debug' || matrix.config.variant == 'release' - run: - ${{ matrix.config.cargo }} test -vv --all-targets --locked ${{ env.CARGO_VARIANT_FLAG }} - --target ${{ matrix.config.target }} + run: ${{ matrix.config.cargo }} nextest run -v --cargo-verbose --cargo-verbose --all-targets --locked --target ${{ matrix.config.target }} ${{ env.CARGO_VARIANT_FLAG }} ${{ env.CARGO_FEATURE_FLAGS }} - name: Clippy - run: - ${{ matrix.config.cargo }} clippy --all-targets --locked ${{ env.CARGO_VARIANT_FLAG }} - --target ${{ matrix.config.target }} -- -D clippy::all + run: ${{ matrix.config.cargo }} clippy --all-targets --locked --target ${{ matrix.config.target }} ${{ env.CARGO_VARIANT_FLAG }} ${{ env.CARGO_FEATURE_FLAGS }} -- -D clippy::all - name: Prepare binary publish if: matrix.config.variant == 'debug' || matrix.config.variant == 'release' run: | - gzip -9c target/${{ matrix.config.target }}/${{ matrix.config.variant }}/gn_out/obj/${{ env.LIB_NAME }}.${{ env.LIB_EXT }} > target/${{ env.LIB_NAME }}_${{ matrix.config.variant }}_${{ matrix.config.target }}.${{ env.LIB_EXT }}.gz - ls -l target/${{ env.LIB_NAME }}_${{ matrix.config.variant }}_${{ matrix.config.target }}.${{ env.LIB_EXT }}.gz + gzip -9c target/${{ matrix.config.target }}/${{ matrix.config.variant }}/gn_out/obj/${{ env.LIB_NAME }}.${{ env.LIB_EXT }} > target/${{ env.LIB_NAME }}${{ env.FEATURES_SUFFIX }}_${{ matrix.config.variant }}_${{ matrix.config.target }}.${{ env.LIB_EXT }}.gz + ls -l target/${{ env.LIB_NAME }}${{ env.FEATURES_SUFFIX }}_${{ matrix.config.variant }}_${{ matrix.config.target }}.${{ env.LIB_EXT }}.gz - cp target/${{ matrix.config.target }}/${{ matrix.config.variant}}/gn_out/src_binding.rs target/src_binding_${{ matrix.config.variant }}_${{ matrix.config.target }}.rs - ls -l target/src_binding_${{ matrix.config.variant }}_${{ matrix.config.target }}.rs + cp target/${{ matrix.config.target }}/${{ matrix.config.variant}}/gn_out/src_binding.rs target/src_binding${{ env.FEATURES_SUFFIX }}_${{ matrix.config.variant }}_${{ matrix.config.target }}.rs + ls -l target/src_binding${{ env.FEATURES_SUFFIX }}_${{ matrix.config.variant }}_${{ matrix.config.target }}.rs - name: Binary publish uses: softprops/action-gh-release@v0.1.15 @@ -229,14 +253,14 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: files: | - target/${{ env.LIB_NAME }}_${{ matrix.config.variant }}_${{ matrix.config.target }}.${{ env.LIB_EXT }}.gz - target/src_binding_${{ matrix.config.variant }}_${{ matrix.config.target }}.rs + target/${{ env.LIB_NAME }}${{ env.FEATURES_SUFFIX }}_${{ matrix.config.variant }}_${{ matrix.config.target }}.${{ env.LIB_EXT }}.gz + target/src_binding${{ env.FEATURES_SUFFIX }}_${{ matrix.config.variant }}_${{ matrix.config.target }}.rs - name: Upload CI artifacts uses: actions/upload-artifact@v4 with: - name: src_binding_${{ matrix.config.variant }}_${{ matrix.config.target }}.rs - path: target/src_binding_${{ matrix.config.variant }}_${{ matrix.config.target }}.rs + name: src_binding${{ env.FEATURES_SUFFIX }}_${{ matrix.config.variant }}_${{ matrix.config.target }}.rs + path: target/src_binding${{ env.FEATURES_SUFFIX }}_${{ matrix.config.variant }}_${{ matrix.config.target }}.rs publish: needs: build diff --git a/.gitmodules b/.gitmodules index 44ef796ab5..929159e6f0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,3 +37,12 @@ [submodule "third_party/fast_float/src"] path = third_party/fast_float/src url = https://chromium.googlesource.com/external/github.com/fastfloat/fast_float.git +[submodule "third_party/llvm-libc/src"] + path = third_party/llvm-libc/src + url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libc.git +[submodule "third_party/simdutf"] + path = third_party/simdutf + url = https://chromium.googlesource.com/chromium/src/third_party/simdutf +[submodule "third_party/highway/src"] + path = third_party/highway/src + url = https://chromium.googlesource.com/external/github.com/google/highway.git diff --git a/.gn b/.gn index 50532a67f6..4376f6c57a 100644 --- a/.gn +++ b/.gn @@ -36,7 +36,6 @@ default_args = { v8_enable_javascript_promise_hooks = true v8_promise_internal_field_count = 1 v8_use_external_startup_data = false - v8_use_snapshot = true v8_enable_pointer_compression = false diff --git a/Cargo.lock b/Cargo.lock index 5874ad3fef..630edea77b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1443,7 +1443,7 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "v8" -version = "130.0.8" +version = "134.2.0" dependencies = [ "align-data", "bindgen", diff --git a/Cargo.toml b/Cargo.toml index e41d788ab6..2225120a5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "v8" -version = "130.0.8" +version = "134.2.0" description = "Rust bindings to V8" readme = "README.md" authors = ["the Deno authors"] @@ -37,6 +37,11 @@ exclude = [ "third_party/libc++/src/utils/", "third_party/libc++/src/www/", "third_party/libc++abi/src/test/", + "third_party/llvm-libc/src/benchmarks/", + "third_party/llvm-libc/src/docs/", + "third_party/llvm-libc/src/fuzzing/", + "third_party/llvm-libc/src/test/", + "third_party/llvm-libc/src/utils/docgen", "third_party/icu/android/", "third_party/icu/android_small/", "third_party/icu/cast/", @@ -56,6 +61,12 @@ exclude = [ "third_party/icu/source/tools/", "third_party/icu/tzres/", "third_party/abseil-cpp/*.def", + "third_party/abseil-cpp/absl/time/internal/cctz/testdata", + "third_party/highway/src/hwy/tests", + "third_party/highway/src/docs", + "third_party/highway/src/g3doc", + "third_party/fp16/src/test", + "third_party/fast_float/src/tests", "tools/clang", "v8/ChangeLog", "v8/benchmarks/", @@ -86,6 +97,7 @@ opt-level = 1 [features] default = ["use_custom_libcxx"] use_custom_libcxx = [] +v8_enable_pointer_compression = [] [dependencies] bitflags = "2.5" diff --git a/README.md b/README.md index 3bbc742e10..27a068d02c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Rusty V8 Binding -V8 Version: 13.0.245.12 +V8 Version: 13.4.114.5 [![ci](https://github.com/denoland/rusty_v8/workflows/ci/badge.svg?branch=main)](https://github.com/denoland/rusty_v8/actions) [![crates](https://img.shields.io/crates/v/v8.svg)](https://crates.io/crates/v8) diff --git a/benches/function.rs b/benches/function.rs index d0d8362cab..52d7947f30 100644 --- a/benches/function.rs +++ b/benches/function.rs @@ -68,8 +68,8 @@ fn main() { const FAST_CALL: v8::fast_api::CFunction = v8::fast_api::CFunction::new( fast_fn as _, &v8::fast_api::CFunctionInfo::new( - v8::fast_api::Type::Int32.scalar(), - &[v8::fast_api::Type::V8Value.scalar()], + v8::fast_api::Type::Int32.as_info(), + &[v8::fast_api::Type::V8Value.as_info()], v8::fast_api::Int64Representation::Number, ), ); diff --git a/build b/build index d0a7da7e88..430d9c2604 160000 --- a/build +++ b/build @@ -1 +1 @@ -Subproject commit d0a7da7e88ffc90355cc94f44d3b5e9084b8381e +Subproject commit 430d9c2604fd5d1d53ee2c0a4a10fdf72b036521 diff --git a/build.rs b/build.rs index 5d204c5191..a8f52fb885 100644 --- a/build.rs +++ b/build.rs @@ -157,6 +157,8 @@ fn build_binding() { .allowlist_item("v8__.*") .allowlist_item("cppgc__.*") .allowlist_item("RustObj") + .allowlist_item("memory_span_t") + .allowlist_item("ExternalConstOneByteStringResource") .generate() .expect("Unable to generate bindings"); @@ -192,10 +194,14 @@ fn build_v8(is_asan: bool) { if is_asan { gn_args.push("is_asan=true".to_string()); } - if env::var("CARGO_FEATURE_USE_CUSTOM_LIBCXX").is_err() { - gn_args.push("use_custom_libcxx=false".to_string()); - } - + gn_args.push(format!( + "use_custom_libcxx={}", + env::var("CARGO_FEATURE_USE_CUSTOM_LIBCXX").is_ok() + )); + gn_args.push(format!( + "v8_enable_pointer_compression={}", + env::var("CARGO_FEATURE_V8_ENABLE_POINTER_COMPRESSION").is_ok() + )); // Fix GN's host_cpu detection when using x86_64 bins on Apple Silicon if cfg!(target_os = "macos") && cfg!(target_arch = "aarch64") { gn_args.push("host_cpu=\"arm64\"".to_string()) @@ -311,7 +317,7 @@ fn build_v8(is_asan: bool) { gn_args.push(r#"target_cpu="x86""#.to_string()); } - let gn_out = maybe_gen(gn_args); + let gn_out = maybe_gen(&gn_args); assert!(gn_out.exists()); assert!(gn_out.join("args.gn").exists()); if env_bool("PRINT_GN_ARGS") { @@ -396,6 +402,14 @@ fn prebuilt_profile() -> &'static str { } } +fn prebuilt_features_suffix() -> String { + let mut features = String::new(); + if env::var("CARGO_FEATURE_V8_ENABLE_POINTER_COMPRESSION").is_ok() { + features.push_str("_ptrcomp"); + } + features +} + fn static_lib_name(suffix: &str) -> String { let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); if target_os == "windows" { @@ -415,11 +429,12 @@ fn static_lib_url() -> String { let version = env::var("CARGO_PKG_VERSION").unwrap(); let target = env::var("TARGET").unwrap(); let profile = prebuilt_profile(); + let features = prebuilt_features_suffix(); format!( "{}/v{}/{}.gz", base, version, - static_lib_name(&format!("_{}_{}", profile, target)), + static_lib_name(&format!("{}_{}_{}", features, profile, target)), ) } @@ -465,14 +480,14 @@ fn replace_non_alphanumeric(url: &str) -> String { .collect() } -fn download_file(url: String, filename: PathBuf) { +fn download_file(url: &str, filename: &Path) { if !url.starts_with("http:") && !url.starts_with("https:") { - copy_archive(&url, &filename); + copy_archive(url, filename); return; } // Checksum (i.e: url) to avoid redownloads - match std::fs::read_to_string(static_checksum_path(&filename)) { + match std::fs::read_to_string(static_checksum_path(filename)) { Ok(c) if c == static_lib_url() => return, _ => {} }; @@ -480,20 +495,15 @@ fn download_file(url: String, filename: PathBuf) { // If there is a `.cargo/.rusty_v8/` file, use that instead // of downloading. if let Ok(mut path) = home::cargo_home() { - path = path.join(".rusty_v8").join(replace_non_alphanumeric(&url)); + path = path.join(".rusty_v8").join(replace_non_alphanumeric(url)); println!("Looking for download in '{path:?}'"); if path.exists() { - copy_archive(&path.to_string_lossy(), &filename); + copy_archive(&path.to_string_lossy(), filename); return; } } - // tmp file to download to so we don't clobber the existing one - let tmpfile = { - let mut t = filename.clone(); - t.set_extension("tmp"); - t - }; + let tmpfile = filename.with_extension("tmp"); if tmpfile.exists() { println!("Deleting old tmpfile {}", tmpfile.display()); std::fs::remove_file(&tmpfile).unwrap(); @@ -505,7 +515,7 @@ fn download_file(url: String, filename: PathBuf) { let status = Command::new(python()) .arg("./tools/download_file.py") .arg("--url") - .arg(&url) + .arg(url) .arg("--filename") .arg(&tmpfile) .status(); @@ -522,7 +532,7 @@ fn download_file(url: String, filename: PathBuf) { .arg("-s") .arg("-o") .arg(&tmpfile) - .arg(&url) + .arg(url) .status() .unwrap() } @@ -533,12 +543,12 @@ fn download_file(url: String, filename: PathBuf) { assert!(tmpfile.exists()); // Write checksum (i.e url) & move file - std::fs::write(static_checksum_path(&filename), url).unwrap(); - copy_archive(&tmpfile.to_string_lossy(), &filename); + std::fs::write(static_checksum_path(filename), url).unwrap(); + copy_archive(&tmpfile.to_string_lossy(), filename); std::fs::remove_file(&tmpfile).unwrap(); assert!(filename.exists()); - assert!(static_checksum_path(&filename).exists()); + assert!(static_checksum_path(filename).exists()); assert!(!tmpfile.exists()); } @@ -550,7 +560,7 @@ fn download_static_lib_binaries() { std::fs::create_dir_all(&dir).unwrap(); println!("cargo:rustc-link-search={}", dir.display()); - download_file(url, static_lib_path()); + download_file(&url, &static_lib_path()); } fn decompress_to_writer(input: &mut R, output: &mut W) -> io::Result<()> @@ -688,14 +698,15 @@ fn print_prebuilt_src_binding_path() { let target = env::var("TARGET").unwrap(); let profile = prebuilt_profile(); - let name = format!("src_binding_{}_{}.rs", profile, target); + let features = prebuilt_features_suffix(); + let name = format!("src_binding{}_{}_{}.rs", features, profile, target); let src_binding_path = get_dirs().root.join("gen").join(name.clone()); if let Ok(base) = env::var("RUSTY_V8_MIRROR") { let version = env::var("CARGO_PKG_VERSION").unwrap(); let url = format!("{}/v{}/{}", base, version, name); - download_file(url, src_binding_path.clone()); + download_file(&url, &src_binding_path); } println!( @@ -707,8 +718,9 @@ fn print_prebuilt_src_binding_path() { // Chromium depot_tools contains helpers // which delegate to the "relevant" `buildtools` // directory when invoked, so they don't count. +#[allow(clippy::needless_pass_by_value)] fn not_in_depot_tools(p: PathBuf) -> bool { - !p.as_path().to_str().unwrap().contains("depot_tools") + !p.to_str().unwrap().contains("depot_tools") } fn need_gn_ninja_download() -> bool { @@ -909,18 +921,16 @@ fn ninja(gn_out_dir: &Path, maybe_env: Option) -> Command { cmd } -pub type GnArgs = Vec; - -pub fn maybe_gen(gn_args: GnArgs) -> PathBuf { +fn maybe_gen(gn_args: &[String]) -> PathBuf { let dirs = get_dirs(); let gn_out_dir = dirs.out.join("gn_out"); if !gn_out_dir.exists() || !gn_out_dir.join("build.ninja").exists() { - let args = if let Ok(extra_args) = env::var("EXTRA_GN_ARGS") { - format!("{} {}", gn_args.join(" "), extra_args) - } else { - gn_args.join(" ") - }; + let mut args = gn_args.join(" "); + if let Ok(extra_args) = env::var("EXTRA_GN_ARGS") { + args.push(' '); + args.push_str(&extra_args); + } let path = env::current_dir().unwrap(); println!("The current directory is {}", path.display()); diff --git a/buildtools b/buildtools index a7a84ac61e..6b4eaa1ed0 160000 --- a/buildtools +++ b/buildtools @@ -1 +1 @@ -Subproject commit a7a84ac61eae5a8946807265a2fd8bd812daf384 +Subproject commit 6b4eaa1ed0f3a604f354b4098e4f676f7815f1da diff --git a/src/array_buffer.rs b/src/array_buffer.rs index 6bdc96bb2e..d4a7adf407 100644 --- a/src/array_buffer.rs +++ b/src/array_buffer.rs @@ -136,12 +136,6 @@ pub struct RustAllocatorVtable { pub allocate_uninitialized: unsafe extern "C" fn(handle: &T, len: usize) -> *mut c_void, pub free: unsafe extern "C" fn(handle: &T, data: *mut c_void, len: usize), - pub reallocate: unsafe extern "C" fn( - handle: &T, - data: *mut c_void, - old_length: usize, - new_length: usize, - ) -> *mut c_void, pub drop: unsafe extern "C" fn(handle: *const T), } @@ -207,14 +201,6 @@ fn test_rust_allocator() { unsafe extern "C" fn free(_: &AtomicUsize, _: *mut c_void, _: usize) { unimplemented!() } - unsafe extern "C" fn reallocate( - _: &AtomicUsize, - _: *mut c_void, - _: usize, - _: usize, - ) -> *mut c_void { - unimplemented!() - } unsafe extern "C" fn drop(x: *const AtomicUsize) { let arc = Arc::from_raw(x); arc.store(42, Ordering::SeqCst); @@ -227,7 +213,6 @@ fn test_rust_allocator() { allocate, allocate_uninitialized, free, - reallocate, drop, }; unsafe { new_rust_allocator(Arc::into_raw(retval.clone()), vtable) }; diff --git a/src/array_buffer_view.rs b/src/array_buffer_view.rs index 88c4d3ffc3..e49a04a896 100644 --- a/src/array_buffer_view.rs +++ b/src/array_buffer_view.rs @@ -1,6 +1,4 @@ -use std::convert::TryInto; -use std::ffi::c_void; - +use crate::binding::memory_span_t; use crate::support::int; use crate::ArrayBuffer; use crate::ArrayBufferView; @@ -8,6 +6,8 @@ use crate::BackingStore; use crate::HandleScope; use crate::Local; use crate::SharedRef; +use std::convert::TryInto; +use std::ffi::c_void; extern "C" { fn v8__ArrayBufferView__Buffer( @@ -23,6 +23,10 @@ extern "C" { dest: *mut c_void, byte_length: int, ) -> usize; + fn v8__ArrayBufferView__GetContents( + this: *const ArrayBufferView, + storage: memory_span_t, + ) -> memory_span_t; } impl ArrayBufferView { @@ -82,4 +86,21 @@ impl ArrayBufferView { ) } } + + #[inline(always)] + pub fn get_contents<'s, 'a>(&'s self, storage: &'a mut [u8]) -> &'a [u8] + where + 's: 'a, + { + unsafe { + let span = v8__ArrayBufferView__GetContents( + self, + memory_span_t { + data: storage.as_mut_ptr() as _, + size: storage.len(), + }, + ); + std::slice::from_raw_parts(span.data as _, span.size) + } + } } diff --git a/src/binding.cc b/src/binding.cc index a86535e0ec..b2853d3d3d 100644 --- a/src/binding.cc +++ b/src/binding.cc @@ -34,6 +34,9 @@ using namespace support; +// TODO(bartlomieju): ideally we could ignore only some of the deprecated APIs +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + template constexpr size_t align_to(size_t size) { return (size + sizeof(T) - 1) & ~(sizeof(T) - 1); @@ -1079,7 +1082,7 @@ const v8::String* v8__String__NewFromTwoByte(v8::Isolate* isolate, int v8__String__Length(const v8::String& self) { return self.Length(); } int v8__String__Utf8Length(const v8::String& self, v8::Isolate* isolate) { - return self.Utf8Length(isolate); + return self.Utf8LengthV2(isolate); } int v8__String__Write(const v8::String& self, v8::Isolate* isolate, @@ -1087,18 +1090,35 @@ int v8__String__Write(const v8::String& self, v8::Isolate* isolate, return self.Write(isolate, buffer, start, length, options); } +void v8__String__Write_v2(const v8::String& self, v8::Isolate* isolate, + uint32_t offset, uint32_t length, uint16_t* buffer, + int flags) { + return self.WriteV2(isolate, offset, length, buffer, flags); +} + int v8__String__WriteOneByte(const v8::String& self, v8::Isolate* isolate, uint8_t* buffer, int start, int length, int options) { return self.WriteOneByte(isolate, buffer, start, length, options); } +void v8__String__WriteOneByte_v2(const v8::String& self, v8::Isolate* isolate, + uint32_t offset, uint32_t length, + uint8_t* buffer, int flags) { + return self.WriteOneByteV2(isolate, offset, length, buffer, flags); +} + int v8__String__WriteUtf8(const v8::String& self, v8::Isolate* isolate, char* buffer, int length, int* nchars_ref, int options) { return self.WriteUtf8(isolate, buffer, length, nchars_ref, options); } +size_t v8__String__WriteUtf8_v2(const v8::String& self, v8::Isolate* isolate, + char* buffer, size_t capacity, int flags) { + return self.WriteUtf8V2(isolate, buffer, capacity, flags); +} + const v8::String::ExternalStringResource* v8__String__GetExternalStringResource( const v8::String& self) { return self.GetExternalStringResource(); @@ -1152,31 +1172,6 @@ class ExternalStaticOneByteStringResource const int _length; }; -// NOTE: This class is never used and only serves as a reference for -// the OneByteConst struct created on Rust-side. -class ExternalConstOneByteStringResource - : public v8::String::ExternalOneByteStringResource { - public: - ExternalConstOneByteStringResource(int length) : _length(length) { - static_assert(offsetof(ExternalConstOneByteStringResource, _length) == - sizeof(size_t) * 2, - "ExternalConstOneByteStringResource's length was not at " - "offset of sizeof(size_t) * 2"); - static_assert( - sizeof(ExternalConstOneByteStringResource) == sizeof(size_t) * 3, - "ExternalConstOneByteStringResource size was not sizeof(size_t) * 3"); - static_assert( - alignof(ExternalConstOneByteStringResource) == sizeof(size_t), - "ExternalConstOneByteStringResource align was not sizeof(size_t)"); - } - const char* data() const override { return nullptr; } - size_t length() const override { return _length; } - void Dispose() override {} - - private: - const int _length; -}; - const v8::String* v8__String__NewExternalOneByteConst( v8::Isolate* isolate, v8::String::ExternalOneByteStringResource* resource) { return maybe_local_to_ptr(v8::String::NewExternalOneByte(isolate, resource)); @@ -1890,12 +1885,18 @@ size_t v8__ArrayBufferView__CopyContents(const v8::ArrayBufferView& self, return ptr_to_local(&self)->CopyContents(dest, byte_length); } +memory_span_t v8__ArrayBufferView__GetContents(const v8::ArrayBufferView& self, + memory_span_t rstorage) { + v8::MemorySpan storage{static_cast(rstorage.data), + rstorage.size}; + v8::MemorySpan span = ptr_to_local(&self)->GetContents(storage); + return {span.data(), span.size()}; +} + struct RustAllocatorVtable { void* (*allocate)(void* handle, size_t length); void* (*allocate_uninitialized)(void* handle, size_t length); void (*free)(void* handle, void* data, size_t length); - void* (*reallocate)(void* handle, void* data, size_t old_length, - size_t new_length); void (*drop)(void* handle); }; @@ -1928,10 +1929,6 @@ class RustAllocator : public v8::ArrayBuffer::Allocator { void Free(void* data, size_t length) final { vtable->free(handle, data, length); } - - void* Reallocate(void* data, size_t old_length, size_t new_length) final { - return vtable->reallocate(handle, data, old_length, new_length); - } }; v8::ArrayBuffer::Allocator* v8__ArrayBuffer__Allocator__NewDefaultAllocator() { diff --git a/src/binding.hpp b/src/binding.hpp index 28aef954fc..fb9670e3a3 100644 --- a/src/binding.hpp +++ b/src/binding.hpp @@ -26,6 +26,9 @@ static int v8__String__kMaxLength = v8::String::kMaxLength; static size_t v8__TypedArray__kMaxByteLength = v8::TypedArray::kMaxByteLength; +static size_t v8__TYPED_ARRAY_MAX_SIZE_IN_HEAP = + V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP; + #define TYPED_ARRAY_MAX_LENGTH(name) \ static size_t v8__##name##__kMaxLength = v8::name::kMaxLength; EACH_TYPED_ARRAY(TYPED_ARRAY_MAX_LENGTH) @@ -33,14 +36,37 @@ EACH_TYPED_ARRAY(TYPED_ARRAY_MAX_LENGTH) using v8__CFunction = v8::CFunction; using v8__CFunctionInfo = v8::CFunctionInfo; -using v8__FastApiArrayBufferView = v8::FastApiArrayBufferView; using v8__FastOneByteString = v8::FastOneByteString; -using v8__FastApiTypedArray = v8::FastApiTypedArray; - using v8__Isolate__UseCounterFeature = v8::Isolate::UseCounterFeature; +using v8__String__WriteFlags = v8::String::WriteFlags; static uint32_t v8__MAJOR_VERSION = V8_MAJOR_VERSION; static uint32_t v8__MINOR_VERSION = V8_MINOR_VERSION; static uint32_t v8__BUILD_NUMBER = V8_BUILD_NUMBER; static uint32_t v8__PATCH_LEVEL = V8_PATCH_LEVEL; static const char* v8__VERSION_STRING = V8_VERSION_STRING; + +// NOTE: This class is never used and only serves as a reference for +// the OneByteConst struct created on Rust-side. +class ExternalConstOneByteStringResource + : public v8::String::ExternalOneByteStringResource { + public: + ExternalConstOneByteStringResource(int length) : _length(length) { + static_assert(offsetof(ExternalConstOneByteStringResource, _length) == + sizeof(size_t) * 2, + "ExternalConstOneByteStringResource's length was not at " + "offset of sizeof(size_t) * 2"); + static_assert( + sizeof(ExternalConstOneByteStringResource) == sizeof(size_t) * 3, + "ExternalConstOneByteStringResource size was not sizeof(size_t) * 3"); + static_assert( + alignof(ExternalConstOneByteStringResource) == sizeof(size_t), + "ExternalConstOneByteStringResource align was not sizeof(size_t)"); + } + const char* data() const override { return nullptr; } + size_t length() const override { return _length; } + void Dispose() override {} + + private: + const int _length; +}; diff --git a/src/fast_api.rs b/src/fast_api.rs index d51dc089e5..7d5ad3c881 100644 --- a/src/fast_api.rs +++ b/src/fast_api.rs @@ -3,7 +3,6 @@ use crate::Isolate; use crate::Local; use crate::Value; use std::ffi::c_void; -use std::marker::PhantomData; #[derive(Clone, Copy)] #[repr(transparent)] @@ -65,14 +64,10 @@ pub enum Int64Representation { pub struct CTypeInfo(v8_CTypeInfo); impl CTypeInfo { - pub const fn new( - r#type: Type, - sequence_type: SequenceType, - flags: Flags, - ) -> Self { + pub const fn new(r#type: Type, flags: Flags) -> Self { Self(v8_CTypeInfo { flags_: flags.bits(), - sequence_type_: sequence_type as _, + sequence_type_: v8_CTypeInfo_SequenceType_kScalar, type_: r#type as _, }) } @@ -99,25 +94,16 @@ pub enum Type { } impl Type { - pub const fn scalar(self) -> CTypeInfo { - CTypeInfo::new(self, SequenceType::Scalar, Flags::empty()) - } - - pub const fn typed_array(self) -> CTypeInfo { - CTypeInfo::new(self, SequenceType::IsTypedArray, Flags::empty()) + // const fn since From is not const + pub const fn as_info(self) -> CTypeInfo { + CTypeInfo::new(self, Flags::empty()) } } -#[derive(Clone, Copy)] -#[repr(u8)] -pub enum SequenceType { - Scalar = v8_CTypeInfo_SequenceType_kScalar, - /// sequence - IsSequence = v8_CTypeInfo_SequenceType_kIsSequence, - /// TypedArray of T or any ArrayBufferView if T is void - IsTypedArray = v8_CTypeInfo_SequenceType_kIsTypedArray, - /// ArrayBuffer - IsArrayBuffer = v8_CTypeInfo_SequenceType_kIsArrayBuffer, +impl From for CTypeInfo { + fn from(t: Type) -> Self { + Self::new(t, Flags::empty()) + } } bitflags::bitflags! { @@ -144,50 +130,6 @@ pub struct FastApiCallbackOptions<'a> { pub data: Local<'a, Value>, } -#[allow(unused)] // only constructed by V8 -#[repr(transparent)] -pub struct FastApiTypedArray(v8__FastApiTypedArray, PhantomData); - -impl FastApiTypedArray { - /// Returns the length in number of elements. - pub const fn length(&self) -> usize { - self.0._base.length_ - } - - /// Performs an unaligned-safe read of T from the underlying data. - #[inline(always)] - pub const fn get(&self, index: usize) -> T { - debug_assert!(index < self.length()); - // SAFETY: src is valid for reads, and is a valid value for T - unsafe { std::ptr::read_unaligned((self.0.data_ as *const T).add(index)) } - } - - /// Returns a slice pointing to the underlying data if safe to do so. - #[inline(always)] - pub fn get_storage_if_aligned(&self) -> Option<&mut [T]> { - // V8 may provide an invalid or null pointer when length is zero, so we just - // ignore that value completely and create an empty slice in this case. - if self.length() == 0 { - return Some(&mut []); - } - let data = self.0.data_ as *mut T; - // Ensure that we never return an unaligned or null buffer - if data.is_null() || !data.is_aligned() { - None - } else { - Some(unsafe { std::slice::from_raw_parts_mut(data, self.length()) }) - } - } -} - -/// Any TypedArray. It uses kTypedArrayBit with base type void -/// Overloaded args of ArrayBufferView and TypedArray are not supported -/// (for now) because the generic “any” ArrayBufferView doesn’t have its -/// own instance type. It could be supported if we specify that -/// TypedArray always has precedence over the generic ArrayBufferView, -/// but this complicates overload resolution. -pub type FastApiArrayBufferView = v8__FastApiArrayBufferView; - pub type FastApiOneByteString = v8__FastOneByteString; impl FastApiOneByteString { diff --git a/src/isolate.rs b/src/isolate.rs index 9899c6e4e9..5f26095f90 100644 --- a/src/isolate.rs +++ b/src/isolate.rs @@ -196,7 +196,7 @@ pub type HostInitializeImportMetaObjectCallback = /// /// The specifier is the name of the module that should be imported. /// -/// The import_assertions are import assertions for this request in the form: +/// The import_attributes are import assertions for this request in the form: /// [key1, value1, key2, value2, ...] where the keys and values are of type /// v8::String. Note, unlike the FixedArray passed to ResolveModuleCallback and /// returned from ModuleRequest::GetImportAssertions(), this array does not @@ -220,7 +220,7 @@ pub type HostInitializeImportMetaObjectCallback = /// host_defined_options: v8::Local<'s, v8::Data>, /// resource_name: v8::Local<'s, v8::Value>, /// specifier: v8::Local<'s, v8::String>, -/// import_assertions: v8::Local<'s, v8::FixedArray>, +/// import_attributes: v8::Local<'s, v8::FixedArray>, /// ) -> Option> { /// todo!() /// } @@ -278,7 +278,7 @@ where host_defined_options: Local<'s, Data>, resource_name: Local<'s, Value>, specifier: Local<'s, String>, - import_assertions: Local<'s, FixedArray>, + import_attributes: Local<'s, FixedArray>, ) -> Option> { let scope = &mut unsafe { CallbackScope::new(context) }; (F::get())( @@ -286,7 +286,7 @@ where host_defined_options, resource_name, specifier, - import_assertions, + import_attributes, ) } @@ -297,14 +297,14 @@ where host_defined_options: Local<'s, Data>, resource_name: Local<'s, Value>, specifier: Local<'s, String>, - import_assertions: Local<'s, FixedArray>, + import_attributes: Local<'s, FixedArray>, ) -> *mut Promise { scope_adapter::( context, host_defined_options, resource_name, specifier, - import_assertions, + import_attributes, ) .map_or_else(null_mut, |return_value| return_value.as_non_null().as_ptr()) } @@ -317,7 +317,7 @@ where host_defined_options: Local<'s, Data>, resource_name: Local<'s, Value>, specifier: Local<'s, String>, - import_assertions: Local<'s, FixedArray>, + import_attributes: Local<'s, FixedArray>, ) -> *mut *mut Promise { unsafe { std::ptr::write( @@ -327,7 +327,7 @@ where host_defined_options, resource_name, specifier, - import_assertions, + import_attributes, ) .map(|return_value| return_value.as_non_null().as_ptr()) .unwrap_or_else(null_mut), @@ -608,7 +608,7 @@ impl Isolate { // Byte offset inside `Isolate` where the isolate data slots are stored. This // should be the same as the value of `kIsolateEmbedderDataOffset` which is // defined in `v8-internal.h`. - const EMBEDDER_DATA_OFFSET: usize = size_of::<[*const (); 67]>(); + const EMBEDDER_DATA_OFFSET: usize = size_of::<[*const (); 73]>(); // Isolate data slots used internally by rusty_v8. const ANNEX_SLOT: u32 = 0; @@ -1262,12 +1262,6 @@ impl Isolate { unsafe { v8__Isolate__PerformMicrotaskCheckpoint(self) } } - /// An alias for PerformMicrotaskCheckpoint. - #[deprecated(note = "Use Isolate::perform_microtask_checkpoint() instead")] - pub fn run_microtasks(&mut self) { - self.perform_microtask_checkpoint() - } - /// Enqueues the callback to the default MicrotaskQueue #[inline(always)] pub fn enqueue_microtask(&mut self, microtask: Local) { diff --git a/src/isolate_create_params.rs b/src/isolate_create_params.rs index 3165218c8f..19abfe4944 100644 --- a/src/isolate_create_params.rs +++ b/src/isolate_create_params.rs @@ -242,7 +242,6 @@ pub(crate) mod raw { pub array_buffer_allocator_shared: SharedPtr, pub external_references: *const intptr_t, pub allow_atomics_wait: bool, - _only_terminate_in_safe_scope: bool, pub embedder_wrapper_type_index: int, pub embedder_wrapper_object_index: int, _fatal_error_handler: *const Opaque, // FatalErrorCallback diff --git a/src/lib.rs b/src/lib.rs index f83a791433..48d5a3aabf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -157,6 +157,7 @@ pub use string::NewStringType; pub use string::OneByteConst; pub use string::ValueView; pub use string::ValueViewData; +pub use string::WriteFlags; pub use string::WriteOptions; pub use support::SharedPtr; pub use support::SharedRef; @@ -190,3 +191,17 @@ pub const VERSION_STRING: &str = // TODO(piscisaureus): Ideally this trait would not be exported. pub use support::MapFnTo; + +pub const TYPED_ARRAY_MAX_SIZE_IN_HEAP: usize = + binding::v8__TYPED_ARRAY_MAX_SIZE_IN_HEAP as _; + +#[cfg(test)] +pub(crate) fn initialize_v8() { + use std::sync::Once; + + static INIT: Once = Once::new(); + INIT.call_once(|| { + V8::initialize_platform(new_default_platform(0, false).make_shared()); + V8::initialize(); + }); +} diff --git a/src/module.rs b/src/module.rs index 22f61cf66f..44c2581968 100644 --- a/src/module.rs +++ b/src/module.rs @@ -21,7 +21,7 @@ use crate::UnboundModuleScript; use crate::Value; /// Called during Module::instantiate_module. Provided with arguments: -/// (context, specifier, import_assertions, referrer). Return None on error. +/// (context, specifier, import_attributes, referrer). Return None on error. /// /// Note: this callback has an unusual signature due to ABI incompatibilities /// between Rust and C++. However end users can implement the callback as @@ -31,7 +31,7 @@ use crate::Value; /// fn my_resolve_callback<'a>( /// context: v8::Local<'a, v8::Context>, /// specifier: v8::Local<'a, v8::String>, -/// import_assertions: v8::Local<'a, v8::FixedArray>, +/// import_attributes: v8::Local<'a, v8::FixedArray>, /// referrer: v8::Local<'a, v8::Module>, /// ) -> Option> { /// // ... @@ -74,10 +74,10 @@ where { #[cfg(not(target_os = "windows"))] fn mapping() -> Self { - let f = |context, specifier, import_assertions, referrer| { + let f = |context, specifier, import_attributes, referrer| { ResolveModuleCallbackRet( - (F::get())(context, specifier, import_assertions, referrer) - .map_or(null(), |r| -> *const Module { &*r }), + (F::get())(context, specifier, import_assertions, referrer + .map_or_else(|| null(), |r| -> *const Module { &*r }), ) }; f.to_c_fn() @@ -85,8 +85,8 @@ where #[cfg(target_os = "windows")] fn mapping() -> Self { - let f = |ret_ptr, context, specifier, import_assertions, referrer| { - let r = (F::get())(context, specifier, import_assertions, referrer) + let f = |ret_ptr, context, specifier, import_attributes, referrer| { + let r = (F::get())(context, specifier, import_attributes, referrer) .map(|r| -> *const Module { &*r }) .unwrap_or(null()); unsafe { std::ptr::write(ret_ptr, r) }; // Write result to stack. @@ -310,8 +310,6 @@ impl Module { /// Returns an empty Maybe if an exception occurred during /// instantiation. (In the case where the callback throws an exception, that /// exception is propagated.) - /// - /// NOTE: requires to set `--harmony-import-assertions` V8 flag. #[must_use] #[inline(always)] pub fn instantiate_module<'a>( @@ -504,10 +502,4 @@ impl ModuleRequest { unsafe { Local::from_raw(v8__ModuleRequest__GetImportAttributes(self)) } .unwrap() } - - #[inline(always)] - #[deprecated(note = "Use get_import_attributes instead")] - pub fn get_import_assertions(&self) -> Local { - self.get_import_attributes() - } } diff --git a/src/scope.rs b/src/scope.rs index 9561336f31..899e19fbe9 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -2260,12 +2260,9 @@ mod raw { #[cfg(test)] mod tests { use super::*; - use crate::new_default_platform; use crate::ContextOptions; use crate::Global; - use crate::V8; use std::any::type_name; - use std::sync::Once; trait SameType {} impl SameType for (A, A) {} @@ -2284,17 +2281,9 @@ mod tests { } } - fn initialize_v8() { - static INIT: Once = Once::new(); - INIT.call_once(|| { - V8::initialize_platform(new_default_platform(0, false).make_shared()); - V8::initialize(); - }); - } - #[test] fn deref_types() { - initialize_v8(); + crate::initialize_v8(); let isolate = &mut Isolate::new(Default::default()); AssertTypeOf(isolate).is::(); let l1_hs = &mut HandleScope::new(isolate); @@ -2468,7 +2457,7 @@ mod tests { #[test] fn new_scope_types() { - initialize_v8(); + crate::initialize_v8(); let isolate = &mut Isolate::new(Default::default()); AssertTypeOf(isolate).is::(); let global_context: Global; diff --git a/src/string.rs b/src/string.rs index 99d92381c9..3d354ae085 100644 --- a/src/string.rs +++ b/src/string.rs @@ -53,6 +53,15 @@ extern "C" { options: WriteOptions, ) -> int; + fn v8__String__Write_v2( + this: *const String, + isolate: *mut Isolate, + offset: u32, + length: u32, + buffer: *mut u16, + flags: int, + ); + fn v8__String__WriteOneByte( this: *const String, isolate: *mut Isolate, @@ -62,6 +71,15 @@ extern "C" { options: WriteOptions, ) -> int; + fn v8__String__WriteOneByte_v2( + this: *const String, + isolate: *mut Isolate, + offset: u32, + length: u32, + buffer: *mut u8, + flags: int, + ); + fn v8__String__WriteUtf8( this: *const String, isolate: *mut Isolate, @@ -71,6 +89,14 @@ extern "C" { options: WriteOptions, ) -> int; + fn v8__String__WriteUtf8_v2( + this: *const String, + isolate: *mut Isolate, + buffer: *mut char, + capacity: size_t, + flags: int, + ) -> int; + fn v8__String__GetExternalStringResource( this: *const String, ) -> *mut ExternalStringResource; @@ -246,11 +272,24 @@ extern "C" fn one_byte_const_length(this: *const OneByteConst) -> usize { // SAFETY: Only called from C++ with a valid OneByteConst pointer. unsafe { (*this).length } } +extern "C" fn one_byte_const_unaccount( + _this: *const OneByteConst, + _isolate: *mut Isolate, +) { +} +extern "C" fn one_byte_const_estimate_memory_usage( + _this: *const OneByteConst, +) -> int { + -1 +} type OneByteConstNoOp = extern "C" fn(*const OneByteConst); type OneByteConstIsCacheable = extern "C" fn(*const OneByteConst) -> bool; type OneByteConstData = extern "C" fn(*const OneByteConst) -> *const char; type OneByteConstLength = extern "C" fn(*const OneByteConst) -> usize; +type OneByteConstUnaccount = extern "C" fn(*const OneByteConst, *mut Isolate); +type OneByteConstEstimateMemoryUsage = + extern "C" fn(*const OneByteConst) -> int; #[repr(C)] struct OneByteConstVtable { @@ -279,6 +318,8 @@ struct OneByteConstVtable { #[cfg(not(target_family = "windows"))] delete2: OneByteConstNoOp, is_cacheable: OneByteConstIsCacheable, + unaccount: OneByteConstUnaccount, + estimate_memory_usage: OneByteConstEstimateMemoryUsage, dispose: OneByteConstNoOp, lock: OneByteConstNoOp, unlock: OneByteConstNoOp, @@ -294,6 +335,8 @@ const ONE_BYTE_CONST_VTABLE: OneByteConstVtable = OneByteConstVtable { #[cfg(not(target_family = "windows"))] delete2: one_byte_const_no_op, is_cacheable: one_byte_const_is_cacheable, + unaccount: one_byte_const_unaccount, + estimate_memory_usage: one_byte_const_estimate_memory_usage, dispose: one_byte_const_no_op, lock: one_byte_const_no_op, unlock: one_byte_const_no_op, @@ -324,6 +367,15 @@ bitflags! { } } +bitflags! { + #[derive(Clone, Copy, Default)] + #[repr(transparent)] + pub struct WriteFlags: int { + const kNullTerminate = crate::binding::v8_String_WriteFlags_kNullTerminate as _; + const kReplaceInvalidUtf8 = crate::binding::v8_String_WriteFlags_kReplaceInvalidUtf8 as _; + } +} + impl String { /// The maximum length (in bytes) of a buffer that a v8::String can be built /// from. Attempting to create a v8::String from a larger buffer will result @@ -420,6 +472,7 @@ impl String { /// Writes the contents of the string to an external buffer, as 16-bit /// (UTF-16) character codes. #[inline(always)] + #[deprecated = "Use `v8::String::write_v2` instead"] pub fn write( &self, scope: &mut Isolate, @@ -439,9 +492,32 @@ impl String { } } + /// Writes the contents of the string to an external buffer, as 16-bit + /// (UTF-16) character codes. + #[inline(always)] + pub fn write_v2( + &self, + scope: &mut Isolate, + offset: u32, + buffer: &mut [u16], + flags: WriteFlags, + ) { + unsafe { + v8__String__Write_v2( + self, + scope, + offset, + self.length().min(buffer.len()) as _, + buffer.as_mut_ptr(), + flags.bits(), + ) + } + } + /// Writes the contents of the string to an external buffer, as one-byte /// (Latin-1) characters. #[inline(always)] + #[deprecated = "Use `v8::String::write_one_byte_v2` instead."] pub fn write_one_byte( &self, scope: &mut Isolate, @@ -461,9 +537,32 @@ impl String { } } + /// Writes the contents of the string to an external buffer, as one-byte + /// (Latin-1) characters. + #[inline(always)] + pub fn write_one_byte_v2( + &self, + scope: &mut Isolate, + offset: u32, + buffer: &mut [u8], + flags: WriteFlags, + ) { + unsafe { + v8__String__WriteOneByte_v2( + self, + scope, + offset, + self.length().min(buffer.len()) as _, + buffer.as_mut_ptr(), + flags.bits(), + ) + } + } + /// Writes the contents of the string to an external [`MaybeUninit`] buffer, as one-byte /// (Latin-1) characters. #[inline(always)] + #[deprecated = "Use `v8::String::write_one_byte_uninit_v2` instead."] pub fn write_one_byte_uninit( &self, scope: &mut Isolate, @@ -483,8 +582,31 @@ impl String { } } + /// Writes the contents of the string to an external [`MaybeUninit`] buffer, as one-byte + /// (Latin-1) characters. + #[inline(always)] + pub fn write_one_byte_uninit_v2( + &self, + scope: &mut Isolate, + offset: u32, + buffer: &mut [MaybeUninit], + flags: WriteFlags, + ) { + unsafe { + v8__String__WriteOneByte_v2( + self, + scope, + offset, + self.length().min(buffer.len()) as _, + buffer.as_mut_ptr() as _, + flags.bits(), + ) + } + } + /// Writes the contents of the string to an external buffer, as UTF-8. #[inline(always)] + #[deprecated = "Use `v8::String::write_utf8_v2` instead."] pub fn write_utf8( &self, scope: &mut Isolate, @@ -496,17 +618,40 @@ impl String { // SAFETY: // We assume that v8 will overwrite the buffer without de-initializing any byte in it. // So the type casting of the buffer is safe. - let buffer = { let len = buffer.len(); let data = buffer.as_mut_ptr().cast(); slice::from_raw_parts_mut(data, len) }; + #[allow(deprecated)] self.write_utf8_uninit(scope, buffer, nchars_ref, options) } } + /// Writes the contents of the string to an external buffer, as UTF-8. + #[inline(always)] + pub fn write_utf8_v2( + &self, + scope: &mut Isolate, + buffer: &mut [u8], + flags: WriteFlags, + ) -> usize { + unsafe { + // SAFETY: + // We assume that v8 will overwrite the buffer without de-initializing any byte in it. + // So the type casting of the buffer is safe. + + let buffer = { + let len = buffer.len(); + let data = buffer.as_mut_ptr().cast(); + slice::from_raw_parts_mut(data, len) + }; + self.write_utf8_uninit_v2(scope, buffer, flags) + } + } + /// Writes the contents of the string to an external [`MaybeUninit`] buffer, as UTF-8. + #[deprecated = "Use `v8::String::write_utf8_uninit_v2` instead."] pub fn write_utf8_uninit( &self, scope: &mut Isolate, @@ -531,6 +676,25 @@ impl String { bytes as usize } + /// Writes the contents of the string to an external [`MaybeUninit`] buffer, as UTF-8. + pub fn write_utf8_uninit_v2( + &self, + scope: &mut Isolate, + buffer: &mut [MaybeUninit], + flags: WriteFlags, + ) -> usize { + let bytes = unsafe { + v8__String__WriteUtf8_v2( + self, + scope, + buffer.as_mut_ptr() as _, + buffer.len(), + flags.bits(), + ) + }; + bytes as usize + } + // Convenience function not present in the original V8 API. #[inline(always)] pub fn new<'s>( @@ -788,18 +952,18 @@ impl String { let buffer = std::ptr::slice_from_raw_parts_mut(data, len_utf16); // Write to this MaybeUninit buffer, assuming we're going to fill this entire buffer - let length = self.write_one_byte_uninit( + self.write_one_byte_uninit_v2( scope, - &mut *buffer, 0, - WriteOptions::NO_NULL_TERMINATION - | WriteOptions::REPLACE_INVALID_UTF8, + &mut *buffer, + WriteFlags::kReplaceInvalidUtf8, ); - debug_assert!(length == len_utf16); // Return an owned string from this guaranteed now-initialized data let buffer = data as *mut u8; - return std::string::String::from_raw_parts(buffer, length, len_utf16); + return std::string::String::from_raw_parts( + buffer, len_utf16, len_utf16, + ); } } @@ -813,11 +977,10 @@ impl String { let buffer = std::ptr::slice_from_raw_parts_mut(data, len_utf8); // Write to this MaybeUninit buffer, assuming we're going to fill this entire buffer - let length = self.write_utf8_uninit( + let length = self.write_utf8_uninit_v2( scope, &mut *buffer, - None, - WriteOptions::NO_NULL_TERMINATION | WriteOptions::REPLACE_INVALID_UTF8, + WriteFlags::kReplaceInvalidUtf8, ); debug_assert!(length == len_utf8); @@ -848,16 +1011,10 @@ impl String { // string is 100% 7-bit ASCII. if self.is_onebyte() && len_utf8 == len_utf16 { if len_utf16 <= N { - let length = self.write_one_byte_uninit( - scope, - buffer, - 0, - WriteOptions::NO_NULL_TERMINATION, - ); - debug_assert!(length == len_utf16); + self.write_one_byte_uninit_v2(scope, 0, buffer, WriteFlags::empty()); unsafe { // Get a slice of &[u8] of what we know is initialized now - let buffer = &mut buffer[..length]; + let buffer = &mut buffer[..len_utf16]; let buffer = &mut *(buffer as *mut [_] as *mut [u8]); // We know it's valid UTF-8, so make a string @@ -873,30 +1030,27 @@ impl String { let buffer = std::ptr::slice_from_raw_parts_mut(data, len_utf16); // Write to this MaybeUninit buffer, assuming we're going to fill this entire buffer - let length = self.write_one_byte_uninit( + self.write_one_byte_uninit_v2( scope, - &mut *buffer, 0, - WriteOptions::NO_NULL_TERMINATION - | WriteOptions::REPLACE_INVALID_UTF8, + &mut *buffer, + WriteFlags::kReplaceInvalidUtf8, ); - debug_assert!(length == len_utf16); // Return an owned string from this guaranteed now-initialized data let buffer = data as *mut u8; return Cow::Owned(std::string::String::from_raw_parts( - buffer, length, len_utf16, + buffer, len_utf16, len_utf16, )); } } if len_utf8 <= N { // No malloc path - let length = self.write_utf8_uninit( + let length = self.write_utf8_uninit_v2( scope, buffer, - None, - WriteOptions::NO_NULL_TERMINATION | WriteOptions::REPLACE_INVALID_UTF8, + WriteFlags::kReplaceInvalidUtf8, ); debug_assert!(length == len_utf8); @@ -921,11 +1075,10 @@ impl String { let buffer = std::ptr::slice_from_raw_parts_mut(data, len_utf8); // Write to this MaybeUninit buffer, assuming we're going to fill this entire buffer - let length = self.write_utf8_uninit( + let length = self.write_utf8_uninit_v2( scope, &mut *buffer, - None, - WriteOptions::NO_NULL_TERMINATION | WriteOptions::REPLACE_INVALID_UTF8, + WriteFlags::kReplaceInvalidUtf8, ); debug_assert!(length == len_utf8); diff --git a/src/support.h b/src/support.h index 87cd632510..505a8a2656 100644 --- a/src/support.h +++ b/src/support.h @@ -178,6 +178,11 @@ struct three_pointers_t { } // namespace support +struct memory_span_t { + void* data; + size_t size; +}; + #define EACH_TYPED_ARRAY(V) \ V(Uint8Array) \ V(Uint8ClampedArray) \ diff --git a/src/symbol.rs b/src/symbol.rs index a118092fed..4ac0a524f2 100644 --- a/src/symbol.rs +++ b/src/symbol.rs @@ -89,23 +89,6 @@ impl Symbol { .unwrap() } - #[deprecated( - since = "0.77.0", - note = "This was documented as `for_key` but implemented as `for_api`" - )] - #[inline(always)] - pub fn for_global<'s>( - scope: &mut HandleScope<'s, ()>, - description: Local, - ) -> Local<'s, Symbol> { - unsafe { - scope.cast_local(|sd| { - v8__Symbol__ForApi(sd.get_isolate_ptr(), &*description) - }) - } - .unwrap() - } - /// Returns the description string of the symbol, or undefined if none. #[inline(always)] pub fn description<'s>( diff --git a/src/typed_array.rs b/src/typed_array.rs index 576be4d7e9..f9da4e520f 100644 --- a/src/typed_array.rs +++ b/src/typed_array.rs @@ -28,6 +28,15 @@ macro_rules! typed_array { ($name:ident) => { paste! { use crate::$name; + + extern "C" { + fn [< v8__ $name __New >]( + buf_ptr: *const ArrayBuffer, + byte_offset: usize, + length: usize, + ) -> *const $name; + } + impl $name { #[inline(always)] pub fn new<'s>( @@ -36,13 +45,6 @@ macro_rules! typed_array { byte_offset: usize, length: usize, ) -> Option> { - extern "C" { - fn [< v8__ $name __New >]( - buf_ptr: *const ArrayBuffer, - byte_offset: usize, - length: usize, - ) -> *const $name; - } unsafe { scope.cast_local(|_| [< v8__ $name __New >](&*buf, byte_offset, length)) } } diff --git a/tests/test_api.rs b/tests/test_api.rs index ed284de72d..4f8a406e1a 100644 --- a/tests/test_api.rs +++ b/tests/test_api.rs @@ -51,7 +51,7 @@ mod setup { )) .is_ok()); v8::V8::set_flags_from_string( - "--no_freeze_flags_after_init --expose_gc --harmony-import-assertions --harmony-shadow-realm --allow_natives_syntax --turbo_fast_api_calls", + "--no_freeze_flags_after_init --expose_gc --harmony-shadow-realm --allow_natives_syntax --turbo_fast_api_calls", ); v8::V8::initialize_platform( v8::new_unprotected_default_platform(0, false).make_shared(), @@ -263,15 +263,12 @@ fn test_string() { assert_eq!(17, local.utf8_length(scope)); assert_eq!(reference, local.to_rust_string_lossy(scope)); let mut vec = vec![0; 17]; - let options = v8::WriteOptions::NO_NULL_TERMINATION; - let mut nchars = 0; assert_eq!( 17, - local.write_utf8(scope, &mut vec, Some(&mut nchars), options) + local.write_utf8_v2(scope, &mut vec, v8::WriteFlags::empty()) ); - assert_eq!(15, nchars); let mut u16_buffer = [0u16; 16]; - assert_eq!(15, local.write(scope, &mut u16_buffer, 0, options)); + local.write_v2(scope, 0, &mut u16_buffer, v8::WriteFlags::empty()); assert_eq!( String::from(reference), String::from_utf16(&u16_buffer[..15]).unwrap() @@ -299,9 +296,8 @@ fn test_string() { .unwrap(); assert_eq!(3, local.length()); assert_eq!(3, local.utf8_length(scope)); - let options = v8::WriteOptions::NO_NULL_TERMINATION; let mut buffer = [0u8; 3]; - assert_eq!(3, local.write_one_byte(scope, &mut buffer, 0, options)); + local.write_one_byte_v2(scope, 0, &mut buffer, v8::WriteFlags::empty()); assert_eq!(b"foo", &buffer); assert_eq!("foo", local.to_rust_string_lossy(scope)); } @@ -639,6 +635,8 @@ fn microtasks() { expected = "v8::OwnedIsolate instances must be dropped in the reverse order of creation. They are entered upon creation and exited upon being dropped." )] fn isolate_drop_order() { + let _setup_guard = setup::parallel_test(); + let isolate1 = v8::Isolate::new(Default::default()); let isolate2 = v8::Isolate::new(Default::default()); drop(isolate1); @@ -1362,7 +1360,7 @@ fn add_message_listener() { fn unexpected_module_resolve_callback<'a>( _context: v8::Local<'a, v8::Context>, _specifier: v8::Local<'a, v8::String>, - _import_assertions: v8::Local<'a, v8::FixedArray>, + _import_attributes: v8::Local<'a, v8::FixedArray>, _referrer: v8::Local<'a, v8::Module>, ) -> Option> { unreachable!() @@ -4882,7 +4880,7 @@ fn module_instantiation_failures1() { fn resolve_callback<'a>( context: v8::Local<'a, v8::Context>, _specifier: v8::Local<'a, v8::String>, - _import_assertions: v8::Local<'a, v8::FixedArray>, + _import_attributes: v8::Local<'a, v8::FixedArray>, _referrer: v8::Local<'a, v8::Module>, ) -> Option> { let scope = &mut unsafe { v8::CallbackScope::new(context) }; @@ -4909,7 +4907,7 @@ fn module_instantiation_failures1() { fn compile_specifier_as_module_resolve_callback<'a>( context: v8::Local<'a, v8::Context>, specifier: v8::Local<'a, v8::String>, - _import_assertions: v8::Local<'a, v8::FixedArray>, + _import_attributes: v8::Local<'a, v8::FixedArray>, _referrer: v8::Local<'a, v8::Module>, ) -> Option> { let scope = &mut unsafe { v8::CallbackScope::new(context) }; @@ -5026,10 +5024,7 @@ fn module_stalled_top_level_await() { } #[test] -fn import_assertions() { - use std::sync::atomic::AtomicUsize; - use std::sync::atomic::Ordering; - +fn import_attributes() { let _setup_guard = setup::parallel_test(); let isolate = &mut v8::Isolate::new(Default::default()); @@ -5039,22 +5034,22 @@ fn import_assertions() { fn module_resolve_callback<'a>( context: v8::Local<'a, v8::Context>, _specifier: v8::Local<'a, v8::String>, - import_assertions: v8::Local<'a, v8::FixedArray>, + import_attributes: v8::Local<'a, v8::FixedArray>, _referrer: v8::Local<'a, v8::Module>, ) -> Option> { let scope = &mut unsafe { v8::CallbackScope::new(context) }; // "type" keyword, value and source offset of assertion - assert_eq!(import_assertions.length(), 3); - let assert1 = import_assertions.get(scope, 0).unwrap(); + assert_eq!(import_attributes.length(), 3); + let assert1 = import_attributes.get(scope, 0).unwrap(); let assert1_val = v8::Local::::try_from(assert1).unwrap(); assert_eq!(assert1_val.to_rust_string_lossy(scope), "type"); - let assert2 = import_assertions.get(scope, 1).unwrap(); + let assert2 = import_attributes.get(scope, 1).unwrap(); let assert2_val = v8::Local::::try_from(assert2).unwrap(); assert_eq!(assert2_val.to_rust_string_lossy(scope), "json"); - let assert3 = import_assertions.get(scope, 2).unwrap(); + let assert3 = import_attributes.get(scope, 2).unwrap(); let assert3_val = v8::Local::::try_from(assert3).unwrap(); - assert_eq!(assert3_val.to_rust_string_lossy(scope), "27"); + assert_eq!(assert3_val.to_rust_string_lossy(scope), "25"); let origin = mock_script_origin(scope, "module.js"); let src = v8::String::new(scope, "export const a = 'a';").unwrap(); @@ -5069,34 +5064,20 @@ fn import_assertions() { _host_defined_options: v8::Local<'s, v8::Data>, _resource_name: v8::Local<'s, v8::Value>, _specifier: v8::Local<'s, v8::String>, - import_assertions: v8::Local<'s, v8::FixedArray>, + import_attributes: v8::Local<'s, v8::FixedArray>, ) -> Option> { // "type" keyword, value - assert_eq!(import_assertions.length(), 2); - let assert1 = import_assertions.get(scope, 0).unwrap(); + assert_eq!(import_attributes.length(), 2); + let assert1 = import_attributes.get(scope, 0).unwrap(); let assert1_val = v8::Local::::try_from(assert1).unwrap(); assert_eq!(assert1_val.to_rust_string_lossy(scope), "type"); - let assert2 = import_assertions.get(scope, 1).unwrap(); + let assert2 = import_attributes.get(scope, 1).unwrap(); let assert2_val = v8::Local::::try_from(assert2).unwrap(); assert_eq!(assert2_val.to_rust_string_lossy(scope), "json"); None } isolate.set_host_import_module_dynamically_callback(dynamic_import_cb); - // TODO(@littledivy): this won't work when V8 removes `assert`. - static COUNTER: AtomicUsize = AtomicUsize::new(0); - extern "C" fn callback( - _msg: v8::Local, - _: v8::Local, - ) { - COUNTER.fetch_add(1, Ordering::SeqCst); - } - - isolate.add_message_listener_with_error_level( - callback, - v8::MessageErrorLevel::ALL, - ); - { let scope = &mut v8::HandleScope::new(isolate); let context = v8::Context::new(scope, Default::default()); @@ -5104,8 +5085,8 @@ fn import_assertions() { let source_text = v8::String::new( scope, - "import 'foo.json' assert { type: \"json\" };\n\ - import('foo.json', { assert: { type: 'json' } });", + "import 'foo.json' with { type: \"json\" };\n\ + import('foo.json', { with: { type: 'json' } });", ) .unwrap(); let origin = mock_script_origin(scope, "foo.js"); @@ -5124,8 +5105,6 @@ fn import_assertions() { assert!(result.unwrap()); assert_eq!(v8::ModuleStatus::Instantiated, module.get_status()); } - - assert_eq!(COUNTER.load(Ordering::SeqCst), 1); } #[test] @@ -5936,7 +5915,7 @@ fn dynamic_import() { _host_defined_options: v8::Local<'s, v8::Data>, _resource_name: v8::Local<'s, v8::Value>, specifier: v8::Local<'s, v8::String>, - _import_assertions: v8::Local<'s, v8::FixedArray>, + _import_attributes: v8::Local<'s, v8::FixedArray>, ) -> Option> { assert!( specifier.strict_equals(v8::String::new(scope, "bar.js").unwrap().into()) @@ -7692,6 +7671,8 @@ fn heap_statistics() { #[test] fn low_memory_notification() { + let _setup_guard = setup::parallel_test(); + let mut isolate = v8::Isolate::new(Default::default()); isolate.low_memory_notification(); } @@ -8917,21 +8898,6 @@ fn run_with_rust_allocator() { count.fetch_sub(n, Ordering::SeqCst); let _ = Box::from_raw(std::slice::from_raw_parts_mut(data as *mut u8, n)); } - unsafe extern "C" fn reallocate( - count: &AtomicUsize, - prev: *mut c_void, - oldlen: usize, - newlen: usize, - ) -> *mut c_void { - count.fetch_add(newlen.wrapping_sub(oldlen), Ordering::SeqCst); - let old_store = - Box::from_raw(std::slice::from_raw_parts_mut(prev as *mut u8, oldlen)); - let mut new_store = Vec::with_capacity(newlen); - let copy_len = oldlen.min(newlen); - new_store.extend_from_slice(&old_store[..copy_len]); - new_store.resize(newlen, 0u8); - Box::into_raw(new_store.into_boxed_slice()) as *mut c_void - } unsafe extern "C" fn drop(count: *const AtomicUsize) { Arc::from_raw(count); } @@ -8941,7 +8907,6 @@ fn run_with_rust_allocator() { allocate, allocate_uninitialized, free, - reallocate, drop, }; let count = Arc::new(AtomicUsize::new(0)); @@ -9249,7 +9214,7 @@ fn code_cache() { fn resolve_callback<'a>( _context: v8::Local<'a, v8::Context>, _specifier: v8::Local<'a, v8::String>, - _import_assertions: v8::Local<'a, v8::FixedArray>, + _import_attributes: v8::Local<'a, v8::FixedArray>, _referrer: v8::Local<'a, v8::Module>, ) -> Option> { None @@ -9608,7 +9573,7 @@ fn compiled_wasm_module() { 0x6F, 0x6F, 0x62, 0x61, 0x72 ] ); - assert_eq!(compiled_module.source_url(), "wasm://wasm/3e495052"); + assert_eq!(compiled_module.source_url(), "wasm://wasm/a1d4c596"); { let isolate = &mut v8::Isolate::new(Default::default()); @@ -9643,6 +9608,8 @@ fn compiled_wasm_module() { #[test] fn function_names() { + let _setup_guard = setup::parallel_test(); + // Setup isolate let isolate = &mut v8::Isolate::new(Default::default()); let scope = &mut v8::HandleScope::new(isolate); @@ -9786,6 +9753,8 @@ fn backing_store_resizable() { #[test] fn current_stack_trace() { + let _setup_guard = setup::parallel_test(); + // Setup isolate let isolate = &mut v8::Isolate::new(Default::default()); let scope = &mut v8::HandleScope::new(isolate); @@ -10468,12 +10437,12 @@ fn test_fast_calls() { const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Uint32.scalar(), + fast_api::Type::Uint32.as_info(), &[ - fast_api::Type::V8Value.scalar(), - fast_api::Type::Uint32.scalar(), - fast_api::Type::Uint32.scalar(), - fast_api::Type::CallbackOptions.scalar(), + fast_api::Type::V8Value.as_info(), + fast_api::Type::Uint32.as_info(), + fast_api::Type::Uint32.as_info(), + fast_api::Type::CallbackOptions.as_info(), ], fast_api::Int64Representation::Number, ), @@ -10525,11 +10494,17 @@ fn test_fast_calls_empty_buffer() { static mut WHO: &str = "none"; unsafe fn fast_fn( _recv: v8::Local, - buffer: *mut fast_api::FastApiTypedArray, + buffer: v8::Local, ) { assert_eq!(WHO, "slow"); WHO = "fast"; - assert_eq!(0, (*buffer).get_storage_if_aligned().unwrap().len()); + assert_eq!( + 0, + buffer + .cast::() + .get_contents(&mut [0; v8::TYPED_ARRAY_MAX_SIZE_IN_HEAP]) + .len() + ); } fn slow_fn( @@ -10545,14 +10520,10 @@ fn test_fast_calls_empty_buffer() { const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Void.scalar(), + fast_api::Type::Void.as_info(), &[ - fast_api::Type::V8Value.scalar(), - fast_api::CTypeInfo::new( - fast_api::Type::Uint8, - fast_api::SequenceType::IsTypedArray, - fast_api::Flags::empty(), - ), + fast_api::Type::V8Value.as_info(), + fast_api::Type::V8Value.as_info(), ], fast_api::Int64Representation::Number, ), @@ -10600,16 +10571,12 @@ fn test_fast_calls_sequence() { const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Uint32.scalar(), + fast_api::Type::Uint32.as_info(), &[ - fast_api::Type::V8Value.scalar(), - fast_api::Type::Uint32.scalar(), - fast_api::Type::Uint32.scalar(), - fast_api::CTypeInfo::new( - fast_api::Type::Void, - fast_api::SequenceType::IsSequence, - fast_api::Flags::empty(), - ), + fast_api::Type::V8Value.as_info(), + fast_api::Type::Uint32.as_info(), + fast_api::Type::Uint32.as_info(), + fast_api::Type::V8Value.as_info(), ], fast_api::Int64Representation::Number, ), @@ -10662,25 +10629,27 @@ fn test_fast_calls_arraybuffer() { _recv: v8::Local, a: u32, b: u32, - data: *const fast_api::FastApiTypedArray, + data: v8::Local, ) -> u32 { unsafe { WHO = "fast" }; - a + b + unsafe { &*data }.get(0) + let data = data.cast::(); + let contents = + data.get_contents(&mut [0; v8::TYPED_ARRAY_MAX_SIZE_IN_HEAP]); + let (x, contents, y) = unsafe { contents.align_to::() }; + assert_eq!(x.len(), 0); + assert_eq!(y.len(), 0); + a + b + contents[0] } const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Uint32.scalar(), + fast_api::Type::Uint32.as_info(), &[ - fast_api::Type::V8Value.scalar(), - fast_api::Type::Uint32.scalar(), - fast_api::Type::Uint32.scalar(), - fast_api::CTypeInfo::new( - fast_api::Type::Uint32, - fast_api::SequenceType::IsTypedArray, - fast_api::Flags::empty(), - ), + fast_api::Type::V8Value.as_info(), + fast_api::Type::Uint32.as_info(), + fast_api::Type::Uint32.as_info(), + fast_api::Type::V8Value.as_info(), ], fast_api::Int64Representation::Number, ), @@ -10729,14 +10698,14 @@ fn test_fast_calls_arraybuffer() { #[test] fn test_fast_calls_typedarray() { static mut WHO: &str = "none"; - fn fast_fn( - _recv: v8::Local, - data: *const fast_api::FastApiTypedArray, - ) -> u32 { + fn fast_fn(_recv: v8::Local, data: v8::Local) -> u32 { unsafe { WHO = "fast" }; - let first = unsafe { &*data }.get(0); - let second = unsafe { &*data }.get(1); - let third = unsafe { &*data }.get(2); + let data = data.cast::(); + let contents = + data.get_contents(&mut [0; v8::TYPED_ARRAY_MAX_SIZE_IN_HEAP]); + let first = contents[0]; + let second = contents[1]; + let third = contents[2]; assert_eq!(first, 4); assert_eq!(second, 5); assert_eq!(third, 6); @@ -10747,14 +10716,10 @@ fn test_fast_calls_typedarray() { const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Uint32.scalar(), + fast_api::Type::Uint32.as_info(), &[ - fast_api::Type::V8Value.scalar(), - fast_api::CTypeInfo::new( - fast_api::Type::Uint8, - fast_api::SequenceType::IsTypedArray, - fast_api::Flags::empty(), - ), + fast_api::Type::V8Value.as_info(), + fast_api::Type::V8Value.as_info(), ], fast_api::Int64Representation::Number, ), @@ -10824,8 +10789,8 @@ fn test_fast_calls_reciever() { const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Uint32.scalar(), - &[fast_api::Type::V8Value.scalar()], + fast_api::Type::Uint32.as_info(), + &[fast_api::Type::V8Value.as_info()], fast_api::Int64Representation::Number, ), ); @@ -10891,33 +10856,24 @@ fn test_fast_calls_reciever() { #[test] fn test_fast_calls_overload() { static mut WHO: &str = "none"; - fn fast_fn( - _recv: v8::Local, - data: *const fast_api::FastApiTypedArray, - ) { - unsafe { WHO = "fast_buf" }; - let buf = unsafe { &*data }; - assert_eq!(buf.length(), 2); - assert_eq!(buf.get(0), 6); - assert_eq!(buf.get(1), 9); + fn fast_fn(_recv: v8::Local, p0: u32) { + unsafe { WHO = "fast_fn" }; + assert_eq!(p0, 1); } - fn fast_fn2(_recv: v8::Local, data: v8::Local) { - unsafe { WHO = "fast_array" }; - assert_eq!(data.length(), 2); + fn fast_fn2(_recv: v8::Local, p0: u32, p1: u32) { + unsafe { WHO = "fast_fn2" }; + assert_eq!(p0, 1); + assert_eq!(p1, 2); } const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Void.scalar(), + fast_api::Type::Void.as_info(), &[ - fast_api::Type::V8Value.scalar(), - fast_api::CTypeInfo::new( - fast_api::Type::Uint32, - fast_api::SequenceType::IsTypedArray, - fast_api::Flags::empty(), - ), + fast_api::Type::V8Value.as_info(), + fast_api::Type::Uint32.as_info(), ], fast_api::Int64Representation::Number, ), @@ -10926,14 +10882,11 @@ fn test_fast_calls_overload() { const FAST_TEST2: fast_api::CFunction = fast_api::CFunction::new( fast_fn2 as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Void.scalar(), + fast_api::Type::Void.as_info(), &[ - fast_api::Type::V8Value.scalar(), - fast_api::CTypeInfo::new( - fast_api::Type::Void, - fast_api::SequenceType::IsSequence, - fast_api::Flags::empty(), - ), + fast_api::Type::V8Value.as_info(), + fast_api::Type::Uint32.as_info(), + fast_api::Type::Uint32.as_info(), ], fast_api::Int64Representation::Number, ), @@ -10963,28 +10916,28 @@ fn test_fast_calls_overload() { let value = template.get_function(scope).unwrap(); global.set(scope, name.into(), value.into()).unwrap(); let source = r#" - function f(data) { return func(data); } - %PrepareFunctionForOptimization(f); - const arr = [6, 9]; - const buf = new Uint32Array(arr); - f(buf); - f(arr); + function f1(p0) { return func(p0); } + function f2(p0, p1) { return func(p0, p1); } + %PrepareFunctionForOptimization(f1); + %PrepareFunctionForOptimization(f2); + f1(1); + f2(1, 2); "#; eval(scope, source).unwrap(); assert_eq!("slow", unsafe { WHO }); let source = r#" - %OptimizeFunctionOnNextCall(f); - f(buf); + %OptimizeFunctionOnNextCall(f1); + f1(1); "#; eval(scope, source).unwrap(); - assert_eq!("fast_buf", unsafe { WHO }); + assert_eq!("fast_fn", unsafe { WHO }); let source = r#" - %OptimizeFunctionOnNextCall(f); - f(arr); + %OptimizeFunctionOnNextCall(f2); + f2(1, 2); "#; eval(scope, source).unwrap(); - assert_eq!("fast_array", unsafe { WHO }); + assert_eq!("fast_fn2", unsafe { WHO }); } #[test] @@ -11007,10 +10960,10 @@ fn test_fast_calls_callback_options_data() { const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Void.scalar(), + fast_api::Type::Void.as_info(), &[ - fast_api::Type::V8Value.scalar(), - fast_api::Type::CallbackOptions.scalar(), + fast_api::Type::V8Value.as_info(), + fast_api::Type::CallbackOptions.as_info(), ], fast_api::Int64Representation::Number, ), @@ -11118,10 +11071,10 @@ fn test_fast_calls_onebytestring() { const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Uint32.scalar(), + fast_api::Type::Uint32.as_info(), &[ - fast_api::Type::V8Value.scalar(), - fast_api::Type::SeqOneByteString.scalar(), + fast_api::Type::V8Value.as_info(), + fast_api::Type::SeqOneByteString.as_info(), ], fast_api::Int64Representation::Number, ), @@ -11183,11 +11136,11 @@ fn test_fast_calls_i64representation() { const FAST_TEST_NUMBER: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Uint64.scalar(), + fast_api::Type::Uint64.as_info(), &[ - fast_api::Type::V8Value.scalar(), - fast_api::Type::Uint64.scalar(), - fast_api::Type::Uint64.scalar(), + fast_api::Type::V8Value.as_info(), + fast_api::Type::Uint64.as_info(), + fast_api::Type::Uint64.as_info(), ], fast_api::Int64Representation::Number, ), @@ -11196,11 +11149,11 @@ fn test_fast_calls_i64representation() { const FAST_TEST_BIGINT: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Uint64.scalar(), + fast_api::Type::Uint64.as_info(), &[ - fast_api::Type::V8Value.scalar(), - fast_api::Type::Uint64.scalar(), - fast_api::Type::Uint64.scalar(), + fast_api::Type::V8Value.as_info(), + fast_api::Type::Uint64.as_info(), + fast_api::Type::Uint64.as_info(), ], fast_api::Int64Representation::BigInt, ), @@ -11362,10 +11315,10 @@ fn test_fast_calls_pointer() { const FAST_TEST: fast_api::CFunction = fast_api::CFunction::new( fast_fn as _, &fast_api::CFunctionInfo::new( - fast_api::Type::Pointer.scalar(), + fast_api::Type::Pointer.as_info(), &[ - fast_api::Type::V8Value.scalar(), - fast_api::Type::Pointer.scalar(), + fast_api::Type::V8Value.as_info(), + fast_api::Type::Pointer.as_info(), ], fast_api::Int64Representation::Number, ), diff --git a/tests/test_platform_atomics_pump_message_loop.rs b/tests/test_platform_atomics_pump_message_loop.rs index 4f3307b9e3..190791acd3 100644 --- a/tests/test_platform_atomics_pump_message_loop.rs +++ b/tests/test_platform_atomics_pump_message_loop.rs @@ -1,8 +1,6 @@ #[test] fn atomics_pump_message_loop() { - v8::V8::set_flags_from_string( - "--allow-natives-syntax --harmony-sharedarraybuffer", - ); + v8::V8::set_flags_from_string("--allow-natives-syntax"); v8::V8::initialize_platform( v8::new_unprotected_default_platform(0, false).make_shared(), ); diff --git a/tests/test_ui.rs b/tests/test_ui.rs index 86f1bcf73b..b2a25f64f8 100644 --- a/tests/test_ui.rs +++ b/tests/test_ui.rs @@ -5,6 +5,10 @@ fn ui() { // This environment variable tells build.rs that we're running trybuild tests, // so it won't rebuild V8. std::env::set_var("DENO_TRYBUILD", "1"); + std::env::set_var( + "RUSTY_V8_SRC_BINDING_PATH", + env!("RUSTY_V8_SRC_BINDING_PATH"), + ); let t = trybuild::TestCases::new(); t.compile_fail("tests/compile_fail/*.rs"); diff --git a/third_party/abseil-cpp b/third_party/abseil-cpp index 1f7e21e34c..aaed376e01 160000 --- a/third_party/abseil-cpp +++ b/third_party/abseil-cpp @@ -1 +1 @@ -Subproject commit 1f7e21e34c3807a8841c9562cfc8b3213eb50bfc +Subproject commit aaed376e01b9f98ff29f70fd47468b7e806e1639 diff --git a/third_party/fast_float/src b/third_party/fast_float/src index 3e57d8dcfb..cb1d42aaa1 160000 --- a/third_party/fast_float/src +++ b/third_party/fast_float/src @@ -1 +1 @@ -Subproject commit 3e57d8dcfb0a04b5a8a26b486b54490a2e9b310f +Subproject commit cb1d42aaa1e14b09e1452cfdef373d051b8c02a4 diff --git a/third_party/highway/src b/third_party/highway/src new file mode 160000 index 0000000000..00fe003dac --- /dev/null +++ b/third_party/highway/src @@ -0,0 +1 @@ +Subproject commit 00fe003dac355b979f36157f9407c7c46448958e diff --git a/third_party/icu b/third_party/icu index 9408c6fd4a..bbccc2f6ef 160000 --- a/third_party/icu +++ b/third_party/icu @@ -1 +1 @@ -Subproject commit 9408c6fd4a39e6fef0e1c4077602e1c83b15f3fb +Subproject commit bbccc2f6efc1b825de5f2c903c48be685cd0cf22 diff --git a/third_party/jinja2 b/third_party/jinja2 index 2f6f2ff5e4..5e1ee241ab 160000 --- a/third_party/jinja2 +++ b/third_party/jinja2 @@ -1 +1 @@ -Subproject commit 2f6f2ff5e4c1d727377f5e1b9e1903d871f41e74 +Subproject commit 5e1ee241ab04b38889f8d517f2da8b3df7cfbd9a diff --git a/third_party/libc++/src b/third_party/libc++/src index 50ab693ecb..2e25154d49 160000 --- a/third_party/libc++/src +++ b/third_party/libc++/src @@ -1 +1 @@ -Subproject commit 50ab693ecb611942ce4440d8c9ed707ee65ed5e8 +Subproject commit 2e25154d49c29fa9aa42c30ad4a027bd30123434 diff --git a/third_party/libc++abi/src b/third_party/libc++abi/src index 29b2e9a0f4..634228a732 160000 --- a/third_party/libc++abi/src +++ b/third_party/libc++abi/src @@ -1 +1 @@ -Subproject commit 29b2e9a0f48688da116692cb04758393053d269c +Subproject commit 634228a732a1d9ae1a6d459556e8fc58707cf961 diff --git a/third_party/libunwind/src b/third_party/libunwind/src index dc70138c3e..e55d8cf51c 160000 --- a/third_party/libunwind/src +++ b/third_party/libunwind/src @@ -1 +1 @@ -Subproject commit dc70138c3e68e2f946585f134e20815851e26263 +Subproject commit e55d8cf51c6db1fdd4bb56c158945ec59772c8ee diff --git a/third_party/llvm-libc/src b/third_party/llvm-libc/src new file mode 160000 index 0000000000..6b4e376d45 --- /dev/null +++ b/third_party/llvm-libc/src @@ -0,0 +1 @@ +Subproject commit 6b4e376d4537ac5c0601bc1459e315a86f0dafd8 diff --git a/third_party/markupsafe b/third_party/markupsafe index 6638e9b0a7..9f8efc8637 160000 --- a/third_party/markupsafe +++ b/third_party/markupsafe @@ -1 +1 @@ -Subproject commit 6638e9b0a79afc2ff7edd9e84b518fe7d5d5fea9 +Subproject commit 9f8efc8637f847ab1ba984212598e6fb9cf1b3d4 diff --git a/third_party/simdutf b/third_party/simdutf new file mode 160000 index 0000000000..5a9a2134b2 --- /dev/null +++ b/third_party/simdutf @@ -0,0 +1 @@ +Subproject commit 5a9a2134b280c1b956ad68a0643797fe26dd1c94 diff --git a/tools/auto_update_v8.ts b/tools/auto_update_v8.ts index 23904bfaa3..8176b9fbdf 100644 --- a/tools/auto_update_v8.ts +++ b/tools/auto_update_v8.ts @@ -1,4 +1,4 @@ -const V8_TRACKING_BRANCH = "13.1-lkgr-denoland"; +const V8_TRACKING_BRANCH = "13.4-lkgr-denoland"; const AUTOROLL_BRANCH = "autoroll"; function extractVersion() { @@ -27,14 +27,19 @@ await run("git", ["submodule", "update", "--init", "--recursive", "v8"]); const currentVersion = extractVersion(); console.log(`Starting auto update. Currently on ${currentVersion}`); -async function run(cmd: string, args: string[], cwd?: string) { +async function run( + cmd: string, + args: string[], + cwd?: string, +): Promise { console.log("$", cmd, ...args); const proc = new Deno.Command(cmd, { args, cwd }); - const status = await proc.output(); - if (!status.success) { + const output = await proc.output(); + if (!output.success) { console.error(`Failed to run ${cmd} ${args.join(" ")}`); Deno.exit(1); } + return output.stdout; } // Update v8 submodule @@ -49,6 +54,14 @@ if (currentVersion == newVersion) { console.log(`Updated to version ${newVersion}`); +// Update V8 dependencies +const depsOutput = await run("python", ["tools/update_deps.py"]); +const depNames = new TextDecoder().decode(depsOutput).split("\n").filter((x) => + x.length > 0 +).at(-1)!.split( + ",", +); + // Update version in readme let readme = Deno.readTextFileSync("README.md"); readme = readme.replace( @@ -58,7 +71,7 @@ readme = readme.replace( Deno.writeTextFileSync("README.md", readme); // Stage the changes -await run("git", ["add", "v8", "README.md"]); +await run("git", ["add", "v8", "README.md", ...depNames]); // Commit the changes await run("git", ["commit", "-m", `Rolling to V8 ${newVersion}`]); diff --git a/tools/clang b/tools/clang index e47c184ec5..a037c8c5ad 160000 --- a/tools/clang +++ b/tools/clang @@ -1 +1 @@ -Subproject commit e47c184ec52d50c7aa2a99cd3bd26ebcafaa94b9 +Subproject commit a037c8c5ad9a5591d9699730ed8c30f3e0a9a5ac diff --git a/tools/update_deps.py b/tools/update_deps.py index 3745602c88..6c7874581b 100644 --- a/tools/update_deps.py +++ b/tools/update_deps.py @@ -14,11 +14,14 @@ def process(name, dep): failed = False +names = [] + with open('.gitmodules') as f: for line in f.readlines(): if line.startswith('['): name = line.split(" ")[1][1:-3] if name in deps: + names.append(name) try: process(name, deps[name]) except: @@ -28,3 +31,4 @@ def process(name, dep): import sys sys.exit(1) +print(','.join(names)) diff --git a/v8 b/v8 index da24147866..8b325d6438 160000 --- a/v8 +++ b/v8 @@ -1 +1 @@ -Subproject commit da24147866cee8f676686056f481734c57e8a8df +Subproject commit 8b325d643843ea36265564eb391508ec2adc28ab