| /* 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/. */ | |
| #[macro_use] | |
| extern crate js; | |
| extern crate libc; | |
| use js::jsapi::{jsfriendapi_h_unnamed_12, DumpHeap}; | |
| use js::glue::CallValueTracer; | |
| use js::jsapi::JS_GC; | |
| use js::jsapi::JSAutoCompartment; | |
| use js::jsapi::CallArgs; | |
| use js::jsapi::CompartmentOptions; | |
| use js::jsapi::GCForReason; | |
| use js::jsapi::GCTraceKindToAscii; | |
| use js::jsapi::GCNurseryProgress; | |
| use js::jsapi::HandleObject; | |
| use js::jsapi::Heap; | |
| use js::jsapi::IsPromiseObject; | |
| use js::jsapi::JSContext; | |
| use js::jsapi::JSGCInvocationKind; | |
| use js::jsapi::JSGCStatus; | |
| use js::jsapi::JSRuntime; | |
| use js::jsapi::JSTracer; | |
| use js::jsapi::JS_AddExtraGCRootsTracer; | |
| use js::jsapi::JS_GetFunctionObject; | |
| use js::jsapi::JS_NewFunction; | |
| use js::jsapi::JS_NewGlobalObject; | |
| use js::jsapi::JS_NewObject; | |
| use js::jsapi::JS_SetGCCallback; | |
| use js::jsapi::NewPromiseObject; | |
| use js::jsapi::OnNewGlobalHookOption; | |
| use js::jsapi::SetGCNurseryCollectionCallback; | |
| use js::jsapi::Reason; | |
| use js::jsval::{UndefinedValue, JSVal, ObjectValue}; | |
| use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS}; | |
| use std::cell::UnsafeCell; | |
| use std::ptr; | |
| use std::os::raw::c_void; | |
| unsafe extern fn do_nothing_promise_executor(_cx: *mut JSContext, argc: u32, vp: *mut JSVal) -> bool { | |
| let args = CallArgs::from_vp(vp, argc); | |
| *args.rval() = UndefinedValue(); | |
| true | |
| } | |
| unsafe extern fn gc_callback(_rt: *mut JSRuntime, _progress: GCNurseryProgress, _reason: Reason) { | |
| //panic!("nursery gc callback") | |
| } | |
| unsafe extern fn gc_callback2(_rt: *mut JSRuntime, _status: JSGCStatus, _data: *mut c_void) { | |
| //panic!("regular gc callback") | |
| } | |
| static mut PROMISE_ROOT: *mut Global = 0 as *mut Global; | |
| struct Global { | |
| v: Option<UnsafeCell<Heap<JSVal>>>, | |
| } | |
| unsafe extern "C" fn trace_promise_root(tr: *mut JSTracer, _data: *mut c_void) { | |
| if PROMISE_ROOT.is_null() { | |
| return; | |
| } | |
| if let Some(ref value) = (*PROMISE_ROOT).v { | |
| let v: &Heap<JSVal> = &*value.get(); | |
| if v.get().is_markable() { | |
| CallValueTracer(tr, v.ptr.get() as *mut _, | |
| GCTraceKindToAscii(v.get().trace_kind())); | |
| } | |
| } | |
| } | |
| #[test] | |
| fn test() { | |
| let rt = Runtime::new(); | |
| let cx = rt.cx(); | |
| let mut g = Global { | |
| v: None, | |
| }; | |
| unsafe { | |
| PROMISE_ROOT = &mut g; | |
| //JS_AddExtraGCRootsTracer(rt.rt(), Some(trace_promise_root), ptr::null_mut()); | |
| let _ = SetGCNurseryCollectionCallback(rt.rt(), Some(gc_callback)); | |
| JS_SetGCCallback(rt.rt(), Some(gc_callback2), ptr::null_mut()); | |
| rooted!(in(cx) let global = | |
| JS_NewGlobalObject(cx, &SIMPLE_GLOBAL_CLASS, ptr::null_mut(), | |
| OnNewGlobalHookOption::FireOnNewGlobalHook, | |
| &CompartmentOptions::default()) | |
| ); | |
| let _ac = JSAutoCompartment::new(cx, global.get()); | |
| let do_nothing_func = JS_NewFunction(cx, | |
| Some(do_nothing_promise_executor), | |
| /* nargs = */ 2, | |
| /* flags = */ 0, | |
| ptr::null()); | |
| { | |
| assert!(!do_nothing_func.is_null()); | |
| rooted!(in(cx) let do_nothing_obj = JS_GetFunctionObject(do_nothing_func)); | |
| assert!(!do_nothing_obj.is_null()); | |
| rooted!(in(cx) let promise = NewPromiseObject(cx, | |
| do_nothing_obj.handle(), | |
| HandleObject::null())); | |
| g.v = Some(UnsafeCell::new(Heap::default())); | |
| (*g.v.as_mut().unwrap().get()).set(ObjectValue(promise.get())); | |
| } | |
| //JS_GC(rt.rt()); | |
| { | |
| //let mut v = vec![]; | |
| //for _ in 1..1000 { | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| rooted!(in(cx) let _foo = JS_NewObject(cx, ptr::null())); | |
| //GCForReason(rt.rt(), JSGCInvocationKind::GC_SHRINK, Reason::OUT_OF_NURSERY); | |
| //} | |
| //MinorGC(cx, false); | |
| } | |
| let fp = libc::fopen(b"/dev/null\0" as *const _ as *const _, b"w\0" as *const _ as *const _); | |
| DumpHeap(rt.rt(), fp, jsfriendapi_h_unnamed_12::CollectNurseryBeforeDump); | |
| libc::fclose(fp); | |
| rooted!(in(cx) let promise = (*g.v.as_ref().unwrap().get()).get().to_object()); | |
| assert!(IsPromiseObject(promise.handle())); | |
| PROMISE_ROOT = ptr::null_mut(); | |
| //JS_SetGCCallback(rt.rt(), None, ptr::null_mut()); | |
| //let _ = SetGCNurseryCollectionCallback(rt.rt(), None); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment