From dae748dee6fb8c1db771364bd12101db1ed34614 Mon Sep 17 00:00:00 2001 From: Redfire Date: Thu, 15 Aug 2024 00:47:22 +0800 Subject: [PATCH] Added Support for External Latin1 Strings (#481) * Added Support for External Latin1 Strings Signed-off-by: Redfire * Reformatted C++ Files with clang-format Added 80 Column Limit to .clang-format Signed-off-by: Redfire * Bumped mozjs-sys Version Fixed Some Compiler Warnings Signed-off-by: Redfire * Added External String Tests Signed-off-by: Redfire --------- Signed-off-by: Redfire --- .clang-format | 5 +- mozjs-sys/Cargo.toml | 2 +- mozjs-sys/src/jsglue.cpp | 32 +++++----- mozjs/src/error.rs | 5 +- mozjs/src/rust.rs | 4 +- mozjs/tests/external_string.rs | 111 +++++++++++++++++++++++++++++++++ 6 files changed, 136 insertions(+), 23 deletions(-) create mode 100644 mozjs/tests/external_string.rs diff --git a/.clang-format b/.clang-format index d663de03612..b951b46bfe8 100644 --- a/.clang-format +++ b/.clang-format @@ -1,9 +1,10 @@ -# Taken from https://searchfox.org/mozilla-central/rev/aa1bb4f0ca8bfda4b117d1befca47b72d5dd6d5d/.clang-format +# Adapted from https://hg.mozilla.org/mozilla-central/file/12bd668f66103e727d3198e600cb25aa4ea8b6dc/.clang-format BasedOnStyle: Google +ColumnLimit: 80 IndentPPDirectives: AfterHash StatementMacros: [MARKUPMAP, ASSERT_TRUE, ASSERT_FALSE, TEST, CHECK] DerivePointerAlignment: false -PointerAlignment: Left \ No newline at end of file +PointerAlignment: Left diff --git a/mozjs-sys/Cargo.toml b/mozjs-sys/Cargo.toml index ef443489401..a0f155d1247 100644 --- a/mozjs-sys/Cargo.toml +++ b/mozjs-sys/Cargo.toml @@ -2,7 +2,7 @@ name = "mozjs_sys" description = "System crate for the Mozilla SpiderMonkey JavaScript engine." repository.workspace = true -version = "0.128.0-7" +version = "0.128.0-8" authors = ["Mozilla"] links = "mozjs" build = "build.rs" diff --git a/mozjs-sys/src/jsglue.cpp b/mozjs-sys/src/jsglue.cpp index 040de2e7809..16d2f2623b8 100644 --- a/mozjs-sys/src/jsglue.cpp +++ b/mozjs-sys/src/jsglue.cpp @@ -144,9 +144,13 @@ class RustReadableStreamUnderlyingSource }; struct JSExternalStringCallbacksTraps { - void (*finalize)(const void* privateData, char16_t* chars); - size_t (*sizeOfBuffer)(const void* privateData, const char16_t* chars, - mozilla::MallocSizeOf mallocSizeOf); + void (*latin1Finalize)(const void* privateData, JS::Latin1Char* chars); + void (*utf16Finalize)(const void* privateData, char16_t* chars); + size_t (*latin1SizeOfBuffer)(const void* privateData, + const JS::Latin1Char* chars, + mozilla::MallocSizeOf mallocSizeOf); + size_t (*utf16SizeOfBuffer)(const void* privateData, const char16_t* chars, + mozilla::MallocSizeOf mallocSizeOf); }; class RustJSExternalStringCallbacks final : public JSExternalStringCallbacks { @@ -158,26 +162,22 @@ class RustJSExternalStringCallbacks final : public JSExternalStringCallbacks { void* privateData) : mTraps(aTraps), privateData(privateData) {} - void finalize(char16_t* chars) const override { - return mTraps.finalize(privateData, chars); + void finalize(JS::Latin1Char* chars) const override { + return mTraps.latin1Finalize(privateData, chars); } - size_t sizeOfBuffer(const char16_t* chars, - mozilla::MallocSizeOf mallocSizeOf) const override { - return mTraps.sizeOfBuffer(privateData, chars, mallocSizeOf); + void finalize(char16_t* chars) const override { + return mTraps.utf16Finalize(privateData, chars); } - void finalize(JS::Latin1Char* chars) const override { - MOZ_ASSERT( - false, - "Latin1Char is not implemented for RustJSExternalStringCallbacks"); + size_t sizeOfBuffer(const JS::Latin1Char* chars, + mozilla::MallocSizeOf mallocSizeOf) const override { + return mTraps.latin1SizeOfBuffer(privateData, chars, mallocSizeOf); } - size_t sizeOfBuffer(const JS::Latin1Char* chars, + size_t sizeOfBuffer(const char16_t* chars, mozilla::MallocSizeOf mallocSizeOf) const override { - MOZ_ASSERT( - false, - "Latin1Char is not implemented for RustJSExternalStringCallbacks"); + return mTraps.utf16SizeOfBuffer(privateData, chars, mallocSizeOf); } }; diff --git a/mozjs/src/error.rs b/mozjs/src/error.rs index aeb078bead2..bd018ddf885 100644 --- a/mozjs/src/error.rs +++ b/mozjs/src/error.rs @@ -9,6 +9,7 @@ use crate::jsapi::{JSContext, JSErrorFormatString, JSExnType, JS_ReportErrorNumberUTF8}; use libc; use std::ffi::CString; +use std::ptr::addr_of; use std::{mem, os, ptr}; /// Format string used to throw javascript errors. @@ -43,8 +44,8 @@ unsafe extern "C" fn get_error_message( ) -> *const JSErrorFormatString { let num: JSExnType = mem::transmute(error_number); match num { - JSExnType::JSEXN_TYPEERR => &TYPE_ERROR_FORMAT_STRING as *const JSErrorFormatString, - JSExnType::JSEXN_RANGEERR => &RANGE_ERROR_FORMAT_STRING as *const JSErrorFormatString, + JSExnType::JSEXN_TYPEERR => addr_of!(TYPE_ERROR_FORMAT_STRING), + JSExnType::JSEXN_RANGEERR => addr_of!(RANGE_ERROR_FORMAT_STRING), _ => panic!( "Bad js error number given to get_error_message: {}", error_number diff --git a/mozjs/src/rust.rs b/mozjs/src/rust.rs index be84e51fe37..3cf6a8bb752 100644 --- a/mozjs/src/rust.rs +++ b/mozjs/src/rust.rs @@ -44,7 +44,7 @@ use crate::jsapi::MutableHandleIdVector as RawMutableHandleIdVector; use crate::jsapi::{already_AddRefed, jsid}; use crate::jsapi::{BuildStackString, CaptureCurrentStack, StackFormat}; use crate::jsapi::{Evaluate2, HandleValueArray, StencilRelease}; -use crate::jsapi::{InitSelfHostedCode, InstantiationStorage, IsWindowSlow}; +use crate::jsapi::{InitSelfHostedCode, IsWindowSlow}; use crate::jsapi::{ JSAutoRealm, JS_SetGCParameter, JS_SetNativeStackQuota, JS_WrapObject, JS_WrapValue, }; @@ -498,7 +498,7 @@ unsafe impl Sync for Stencil {}*/ impl Drop for Stencil { fn drop(&mut self) { - if (self.is_null()) { + if self.is_null() { return; } unsafe { diff --git a/mozjs/tests/external_string.rs b/mozjs/tests/external_string.rs new file mode 100644 index 00000000000..4886ab3522c --- /dev/null +++ b/mozjs/tests/external_string.rs @@ -0,0 +1,111 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use std::ffi::c_void; +use std::ptr; + +use mozjs::conversions::jsstr_to_string; +use mozjs::glue::{CreateJSExternalStringCallbacks, JSExternalStringCallbacksTraps}; +use mozjs::jsapi::{ + JSAutoRealm, JS_NewExternalStringLatin1, JS_NewExternalUCString, JS_NewGlobalObject, + OnNewGlobalHookOption, +}; +use mozjs::rooted; +use mozjs::rust::{JSEngine, RealmOptions, Runtime, SIMPLE_GLOBAL_CLASS}; + +#[test] +fn external_string() { + let engine = JSEngine::init().unwrap(); + let runtime = Runtime::new(engine.handle()); + let context = runtime.cx(); + let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook; + let c_option = RealmOptions::default(); + + unsafe { + rooted!(in(context) let global = JS_NewGlobalObject( + context, + &SIMPLE_GLOBAL_CLASS, + ptr::null_mut(), + h_option, + &*c_option, + )); + let _ac = JSAutoRealm::new(context, global.get()); + + let latin1_base = "test latin-1"; + let latin1_boxed = latin1_base.as_bytes().to_vec().into_boxed_slice(); + let latin1_chars = Box::into_raw(latin1_boxed).cast::(); + + let callbacks = CreateJSExternalStringCallbacks( + &EXTERNAL_STRING_CALLBACKS_TRAPS, + latin1_base.len() as *mut c_void, + ); + rooted!(in(context) let latin1_jsstr = JS_NewExternalStringLatin1( + context, + latin1_chars, + latin1_base.len(), + callbacks + )); + assert_eq!(jsstr_to_string(context, latin1_jsstr.get()), latin1_base); + + let utf16_base = "test utf-16 $€ \u{10437}\u{24B62}"; + let utf16_boxed = utf16_base + .encode_utf16() + .collect::>() + .into_boxed_slice(); + let utf16_len = utf16_boxed.len(); + let utf16_chars = Box::into_raw(utf16_boxed).cast::(); + + let callbacks = CreateJSExternalStringCallbacks( + &EXTERNAL_STRING_CALLBACKS_TRAPS, + utf16_len as *mut c_void, + ); + rooted!(in(context) let utf16_jsstr = JS_NewExternalUCString( + context, + utf16_chars, + utf16_len, + callbacks + )); + assert_eq!(jsstr_to_string(context, utf16_jsstr.get()), utf16_base); + } +} + +static EXTERNAL_STRING_CALLBACKS_TRAPS: JSExternalStringCallbacksTraps = + JSExternalStringCallbacksTraps { + latin1Finalize: Some(latin1::finalize), + latin1SizeOfBuffer: Some(latin1::size_of), + utf16Finalize: Some(utf16::finalize), + utf16SizeOfBuffer: Some(utf16::size_of), + }; + +mod latin1 { + use std::ffi::c_void; + use std::slice; + + use mozjs::jsapi::mozilla::MallocSizeOf; + + pub unsafe extern "C" fn finalize(data: *const c_void, chars: *mut u8) { + let slice = slice::from_raw_parts_mut(chars, data as usize); + let _ = Box::from_raw(slice); + } + + pub unsafe extern "C" fn size_of(data: *const c_void, _: *const u8, _: MallocSizeOf) -> usize { + data as usize + } +} + +mod utf16 { + use std::ffi::c_void; + use std::slice; + + use mozjs::jsapi::mozilla::MallocSizeOf; + + pub unsafe extern "C" fn finalize(data: *const c_void, chars: *mut u16) { + let slice = slice::from_raw_parts_mut(chars, data as usize); + let _ = Box::from_raw(slice); + } + + pub unsafe extern "C" fn size_of(data: *const c_void, _: *const u16, _: MallocSizeOf) -> usize { + data as usize + } +}