Skip to content

Commit 4584c11

Browse files
wip
1 parent 9dc5ad4 commit 4584c11

File tree

9 files changed

+230
-27
lines changed

9 files changed

+230
-27
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# 0.12.0
22

3-
* uses hirofa-quickjs-sys 0.10.0 and ['bellard'] feature and thus the 2023-12-09 version of the original quickjs by Fabrice Bellard
3+
* uses hirofa-quickjs-sys 0.2.0 and ['bellard'] feature and thus the 2024-01-13 version of the original quickjs by Fabrice Bellard
44
* added get_proxy_instance_id for getting instance id without looking up the proxy
55
* console functions output source filename
66

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ hirofa_utils = "0.7"
2828
#hirofa_utils = {git="https://github.com/HiRoFa/utils"}
2929
backtrace = "0.3.67"
3030

31-
libquickjs-sys = {package="hirofa-quickjs-sys", git='https://github.com/HiRoFa/quickjs-sys', features=["bellard"]}
31+
#libquickjs-sys = {package="hirofa-quickjs-sys", git='https://github.com/HiRoFa/quickjs-sys', features=["bellard"]}
3232
#libquickjs-sys = {package="hirofa-quickjs-sys", path='../quickjs-sys', features=["bellard"]}
33+
libquickjs-sys = {package="hirofa-quickjs-sys", version="0.2.0", features=["bellard"]}
3334
lazy_static = "1.4.0"
3435
log = "0.4"
3536
num_cpus = "1"

src/facades.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ impl QuickJsRuntimeFacade {
212212
std::thread::spawn(move || loop {
213213
std::thread::sleep(interval);
214214
if let Some(el) = rti_ref.upgrade() {
215-
log::trace!("running gc from gc interval thread");
215+
log::debug!("running gc from gc interval thread");
216216
el.event_loop.add_void(|| {
217217
QJS_RT
218218
.try_with(|rc| {
@@ -1079,12 +1079,12 @@ pub mod tests {
10791079
fn test_func() {
10801080
let rt = init_test_rt();
10811081
let res = rt.set_function(&["nl", "my", "utils"], "methodA", |_q_ctx, args| {
1082-
if args.len() != 2 || !args.get(0).unwrap().is_i32() || !args.get(1).unwrap().is_i32() {
1082+
if args.len() != 2 || !args.first().unwrap().is_i32() || !args.get(1).unwrap().is_i32() {
10831083
Err(JsError::new_str(
10841084
"i'd really like 2 args of the int32 kind please",
10851085
))
10861086
} else {
1087-
let a = args.get(0).unwrap().get_i32();
1087+
let a = args.first().unwrap().get_i32();
10881088
let b = args.get(1).unwrap().get_i32();
10891089
Ok((a * b).to_js_value_facade())
10901090
}

src/quickjs_utils/functions.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ pub unsafe fn call_to_string(
234234
obj_ref: &QuickJsValueAdapter,
235235
) -> Result<String, JsError> {
236236
if obj_ref.is_string() {
237-
crate::quickjs_utils::primitives::to_string(context, obj_ref)
237+
primitives::to_string(context, obj_ref)
238238
} else if obj_ref.is_null() {
239239
Ok("null".to_string())
240240
} else if obj_ref.is_undefined() {
@@ -264,7 +264,7 @@ pub unsafe fn call_to_string(
264264
if !res_ref.is_string() {
265265
return Err(JsError::new_str("Could not convert value to string"));
266266
}
267-
crate::quickjs_utils::primitives::to_string(context, &res_ref)
267+
primitives::to_string(context, &res_ref)
268268
}
269269
}
270270

@@ -529,11 +529,11 @@ thread_local! {
529529
RefCell::new(class_id)
530530
};
531531

532-
static CALLBACK_REGISTRY: RefCell<AutoIdMap<(String, Rc<Callback>)>> = {
532+
pub static CALLBACK_REGISTRY: RefCell<AutoIdMap<(String, Rc<Callback>)>> = {
533533
RefCell::new(AutoIdMap::new_with_max_size(i32::MAX as usize))
534534
};
535535

536-
static CALLBACK_IDS: RefCell<HashSet<Box<i32>>> = RefCell::new(HashSet::new());
536+
pub static CALLBACK_IDS: RefCell<HashSet<Box<i32>>> = RefCell::new(HashSet::new());
537537
}
538538

539539
pub(crate) fn init_statics() {

src/quickjs_utils/promises.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ pub mod tests {
382382
q_ctx,
383383
"testThen",
384384
|_q_ctx, _this, args| {
385-
let res = primitives::to_i32(args.get(0).unwrap()).ok().unwrap();
385+
let res = primitives::to_i32(args.first().unwrap()).ok().unwrap();
386386
log::trace!("prom resolved with: {}", res);
387387
Ok(new_null_ref())
388388
},

src/quickjs_utils/typedarrays.rs

Lines changed: 134 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use std::cell::RefCell;
5353

5454
thread_local! {
5555
// max size is 32.max because we store id as prop
56-
static BUFFERS: RefCell<AutoIdMap<Vec<u8>>> = RefCell::new(AutoIdMap::new_with_max_size(i32::MAX as usize));
56+
pub static BUFFERS: RefCell<AutoIdMap<Vec<u8>>> = RefCell::new(AutoIdMap::new_with_max_size(i32::MAX as usize));
5757
}
5858

5959
/// this method creates a new ArrayBuffer which is used as a basis for all typed arrays
@@ -73,6 +73,8 @@ pub unsafe fn new_array_buffer(
7373
ctx: *mut q::JSContext,
7474
buf: Vec<u8>,
7575
) -> Result<QuickJsValueAdapter, JsError> {
76+
log::trace!("new_array_buffer");
77+
7678
#[cfg(target_pointer_width = "64")]
7779
let length = buf.len();
7880
#[cfg(target_pointer_width = "32")]
@@ -156,6 +158,8 @@ pub unsafe fn new_array_buffer_copy(
156158
ctx: *mut q::JSContext,
157159
buf: &[u8],
158160
) -> Result<QuickJsValueAdapter, JsError> {
161+
log::trace!("new_array_buffer_copy");
162+
159163
#[cfg(target_pointer_width = "64")]
160164
let length = buf.len();
161165
#[cfg(target_pointer_width = "32")]
@@ -190,6 +194,8 @@ pub unsafe fn detach_array_buffer_buffer(
190194
ctx: *mut q::JSContext,
191195
array_buffer: &QuickJsValueAdapter,
192196
) -> Result<Vec<u8>, JsError> {
197+
log::trace!("detach_array_buffer_buffer");
198+
193199
debug_assert!(is_array_buffer(ctx, array_buffer));
194200

195201
// check if vec is one we buffered, if not we create a new one from the slice we got from quickjs
@@ -243,16 +249,33 @@ pub unsafe fn get_array_buffer_buffer_copy(
243249
) -> Result<Vec<u8>, JsError> {
244250
debug_assert!(is_array_buffer(ctx, array_buffer));
245251

246-
#[cfg(target_pointer_width = "64")]
247-
let mut len: usize = 0;
248-
#[cfg(target_pointer_width = "32")]
249-
let mut len: u32 = 0;
252+
log::trace!("get_array_buffer_buffer_copy");
253+
254+
let id_prop = get_property(ctx, array_buffer, "__buffer_id")?;
255+
let id_opt = if id_prop.is_i32() {
256+
Some(id_prop.to_i32() as usize)
257+
} else {
258+
None
259+
};
260+
261+
if let Some(id) = id_opt {
262+
let b = BUFFERS.with(|rc| {
263+
let buffers = &mut *rc.borrow_mut();
264+
buffers.get(&id).expect("invalid buffer state").clone()
265+
});
266+
Ok(b)
267+
} else {
268+
#[cfg(target_pointer_width = "64")]
269+
let mut len: usize = 0;
270+
#[cfg(target_pointer_width = "32")]
271+
let mut len: u32 = 0;
250272

251-
let ptr = q::JS_GetArrayBuffer(ctx, &mut len, *array_buffer.borrow_value());
273+
let ptr = q::JS_GetArrayBuffer(ctx, &mut len, *array_buffer.borrow_value());
252274

253-
let slice = std::slice::from_raw_parts(ptr, len as _);
275+
let slice = std::slice::from_raw_parts(ptr, len as _);
254276

255-
Ok(slice.to_vec())
277+
Ok(slice.to_vec())
278+
}
256279
}
257280

258281
/// get the underlying ArrayBuffer of a TypedArray
@@ -276,6 +299,7 @@ pub unsafe fn get_array_buffer(
276299

277300
// todo!();
278301
// for our Uint8Array uses cases this works fine
302+
log::trace!("get_array_buffer");
279303
get_property(ctx, typed_array, "buffer")
280304
}
281305

@@ -324,11 +348,13 @@ unsafe extern "C" fn free_func(
324348
opaque: *mut ::std::os::raw::c_void,
325349
ptr: *mut ::std::os::raw::c_void,
326350
) {
351+
let id = opaque as usize;
352+
log::trace!("typedarrays::free_func {}", id);
353+
327354
if ptr.is_null() {
328355
return;
329356
}
330357

331-
let id = opaque as usize;
332358
BUFFERS.with(|rc| {
333359
let buffers = &mut *rc.borrow_mut();
334360
if buffers.contains_key(&id) {
@@ -340,14 +366,23 @@ unsafe extern "C" fn free_func(
340366
#[cfg(test)]
341367
pub mod tests {
342368
use crate::builder::QuickJsRuntimeBuilder;
343-
use crate::jsutils::Script;
369+
use crate::jsutils::{JsError, Script};
344370
use crate::quickjs_utils::typedarrays::{
345-
detach_array_buffer_buffer_q, get_array_buffer_q, is_array_buffer_q, is_typed_array_q,
346-
new_array_buffer_q, new_uint8_array_q,
371+
detach_array_buffer_buffer_q, get_array_buffer_buffer_copy_q, get_array_buffer_q,
372+
is_array_buffer_q, is_typed_array_q, new_array_buffer_q, new_uint8_array_copy_q,
373+
new_uint8_array_q,
347374
};
375+
use crate::values::{JsValueFacade, TypedArrayType};
376+
377+
use crate::quickjs_utils::objects::set_property_q;
378+
use crate::quickjs_utils::{get_global_q, new_undefined_ref};
379+
use std::thread;
380+
use std::time::Duration;
348381

349382
#[test]
350383
fn test_typed() {
384+
simple_logging::log_to_stderr(log::LevelFilter::max());
385+
351386
std::panic::set_hook(Box::new(|panic_info| {
352387
let backtrace = backtrace::Backtrace::new();
353388
println!("thread panic occurred: {panic_info}\nbacktrace: {backtrace:?}");
@@ -358,7 +393,56 @@ pub mod tests {
358393
);
359394
}));
360395

361-
//simple_logging::log_to_stderr(log::LevelFilter::max());
396+
let rt = QuickJsRuntimeBuilder::new().build();
397+
398+
let res: Result<(), JsError> = rt.exe_rt_task_in_event_loop(|rt| {
399+
let mut buffer: Vec<u8> = vec![];
400+
for y in 0..(10 * 1024 * 1024) {
401+
buffer.push(y as u8);
402+
}
403+
404+
let realm = rt.get_main_realm();
405+
let adapter = new_uint8_array_copy_q(realm, &buffer)?;
406+
drop(buffer);
407+
let global = get_global_q(realm);
408+
set_property_q(realm, &global, "buf", &adapter)?;
409+
410+
drop(adapter);
411+
412+
realm.eval(Script::new(
413+
"l.js",
414+
"console.log(`buf l=%s 1=%s`, globalThis.buf.length, globalThis.buf[1]);",
415+
))?;
416+
417+
set_property_q(realm, &global, "buf", &new_undefined_ref())?;
418+
419+
rt.gc();
420+
421+
Ok(())
422+
});
423+
match res {
424+
Ok(_) => {
425+
log::info!("done ok");
426+
}
427+
Err(err) => {
428+
panic!("{err}");
429+
}
430+
}
431+
}
432+
433+
#[test]
434+
fn test_typed2() {
435+
simple_logging::log_to_stderr(log::LevelFilter::max());
436+
437+
std::panic::set_hook(Box::new(|panic_info| {
438+
let backtrace = backtrace::Backtrace::new();
439+
println!("thread panic occurred: {panic_info}\nbacktrace: {backtrace:?}");
440+
log::error!(
441+
"thread panic occurred: {}\nbacktrace: {:?}",
442+
panic_info,
443+
backtrace
444+
);
445+
}));
362446

363447
let rt = QuickJsRuntimeBuilder::new().build();
364448

@@ -379,7 +463,7 @@ pub mod tests {
379463
realm
380464
.eval(Script::new(
381465
"testu8",
382-
"globalThis.testTyped = function(typedArray) {console.log('t=%s len=%s 0=%s 1=%s 2=%s', typedArray.constructor.name, typedArray.length, typedArray[0], typedArray[1], typedArray[2]); typedArray[0] = 34;};",
466+
"globalThis.testTyped = function(typedArray) {console.log('t=%s len=%s 0=%s 1=%s 2=%s', typedArray.constructor.name, typedArray.length, typedArray[0], typedArray[1], typedArray[2]); typedArray[0] = 34; const ret = []; for (let x = 0; x < 1024; x++) {ret.push(x);}; return new Uint8Array(ret);};",
383467
))
384468
.expect("script failed");
385469
});
@@ -410,7 +494,7 @@ pub mod tests {
410494
match arr_res {
411495
Ok(mut arr) => {
412496
arr.label("arr");
413-
log::debug!("arr created");
497+
log::debug!("arr created, refcount={}", arr.get_ref_count());
414498

415499
assert!(is_typed_array_q(realm, &arr));
416500

@@ -420,6 +504,9 @@ pub mod tests {
420504

421505
let ab = get_array_buffer_q(realm, &arr).expect("did not get buffer");
422506

507+
let copy = get_array_buffer_buffer_copy_q(realm, &ab).expect("could not copy");
508+
log::info!("copy.len = {}", copy.len());
509+
423510
log::trace!("reclaiming");
424511
let buf2_reclaimed =
425512
detach_array_buffer_buffer_q(realm, &ab).expect("detach failed");
@@ -452,5 +539,37 @@ pub mod tests {
452539
}
453540
}
454541
});
542+
543+
thread::sleep(Duration::from_secs(1));
544+
545+
for x in 0..10 {
546+
let mut buffer2: Vec<u8> = vec![];
547+
for y in 0..(10 * 1024 * 1024) {
548+
buffer2.push(y as u8);
549+
}
550+
let ta = JsValueFacade::TypedArray {
551+
buffer: buffer2,
552+
array_type: TypedArrayType::Uint8,
553+
};
554+
let res = rt.invoke_function_sync(None, &[], "testTyped", vec![ta]);
555+
match res {
556+
Ok(r) => {
557+
log::info!("from jsvf got {:?}", r);
558+
}
559+
Err(e) => {
560+
panic!("{}", e);
561+
}
562+
}
563+
log::info!("x={x}");
564+
}
565+
566+
drop(rt);
567+
568+
crate::quickjs_utils::typedarrays::BUFFERS.with(|rc| {
569+
let buffers = &mut *rc.borrow_mut();
570+
log::info!("BUFFERS.len = {}", buffers.len());
571+
});
572+
573+
thread::sleep(Duration::from_secs(1));
455574
}
456575
}

0 commit comments

Comments
 (0)