Skip to content

Instantly share code, notes, and snippets.

@jdm
Created January 18, 2017 22:49
Show Gist options
  • Save jdm/b36d32d887e1fd6887b6d60c6cae218d to your computer and use it in GitHub Desktop.
Save jdm/b36d32d887e1fd6887b6d60c6cae218d to your computer and use it in GitHub Desktop.
/* 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