Skip to content

Commit

Permalink
Added Support for External Latin1 Strings (#481)
Browse files Browse the repository at this point in the history
* Added Support for External Latin1 Strings

Signed-off-by: Redfire <[email protected]>

* Reformatted C++ Files with clang-format

Added 80 Column Limit to .clang-format

Signed-off-by: Redfire <[email protected]>

* Bumped mozjs-sys Version

Fixed Some Compiler Warnings

Signed-off-by: Redfire <[email protected]>

* Added External String Tests

Signed-off-by: Redfire <[email protected]>

---------

Signed-off-by: Redfire <[email protected]>
  • Loading branch information
Redfire75369 authored Aug 14, 2024
1 parent 69c3a51 commit dae748d
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 23 deletions.
5 changes: 3 additions & 2 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -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
PointerAlignment: Left
2 changes: 1 addition & 1 deletion mozjs-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
32 changes: 16 additions & 16 deletions mozjs-sys/src/jsglue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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);
}
};

Expand Down
5 changes: 3 additions & 2 deletions mozjs/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions mozjs/src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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 {
Expand Down
111 changes: 111 additions & 0 deletions mozjs/tests/external_string.rs
Original file line number Diff line number Diff line change
@@ -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::<u8>();

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::<Vec<_>>()
.into_boxed_slice();
let utf16_len = utf16_boxed.len();
let utf16_chars = Box::into_raw(utf16_boxed).cast::<u16>();

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
}
}

0 comments on commit dae748d

Please sign in to comment.