[quickjs][oden][oden-js] Source maps
The worst support but it should cost very little if nobody is using them (psst we're using them)
This commit is contained in:
parent
eb9fed759a
commit
c96a1a4979
10 changed files with 554 additions and 374 deletions
|
|
@ -1,8 +1,8 @@
|
|||
use crate::{
|
||||
module::loader::{load_module, DefaultModuleLoader, ModuleLoader},
|
||||
module::loader::{DefaultModuleLoader, ModuleLoader, ModuleSource},
|
||||
promise::{PromiseEvent, PromiseHandle},
|
||||
ContextRef, DefaultRejectedPromiseTracker, Promise, RejectedPromiseTracker, Result, Value,
|
||||
ValueRef,
|
||||
throw_error, Atom, AtomRef, ContextRef, DefaultRejectedPromiseTracker, Promise,
|
||||
RejectedPromiseTracker, Result, Value, ValueRef,
|
||||
};
|
||||
use oden_js_sys as sys;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
|
|
@ -42,7 +42,7 @@ impl Drop for PromiseEntry {
|
|||
|
||||
struct PrivateState {
|
||||
refs: u64,
|
||||
loader: Arc<Box<dyn ModuleLoader>>,
|
||||
loader: Arc<RefCell<Box<dyn ModuleLoader>>>,
|
||||
promise_send: Sender<(PromiseHandle, PromiseEvent)>,
|
||||
promise_recv: Receiver<(PromiseHandle, PromiseEvent)>,
|
||||
promise_table: HashMap<PromiseHandle, PromiseEntry>, // !
|
||||
|
|
@ -54,7 +54,7 @@ impl PrivateState {
|
|||
let (send, recv) = channel();
|
||||
Box::new(RefCell::new(PrivateState {
|
||||
refs: 1,
|
||||
loader: Arc::new(Box::new(DefaultModuleLoader::new())),
|
||||
loader: Arc::new(RefCell::new(Box::new(DefaultModuleLoader::new()))),
|
||||
promise_send: send,
|
||||
promise_recv: recv,
|
||||
promise_table: HashMap::new(),
|
||||
|
|
@ -90,7 +90,64 @@ impl PrivateState {
|
|||
.clone()
|
||||
};
|
||||
let context = ContextRef::from_raw(ctx);
|
||||
load_module(&context, path, &loader)
|
||||
|
||||
let result = {
|
||||
let mut loader = loader.borrow_mut();
|
||||
loader.load(&context, path)
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(ModuleSource::Native(native)) => native.module,
|
||||
Ok(ModuleSource::JavaScript(js)) => match context.eval_module(&js, path) {
|
||||
Ok(v) => v.module,
|
||||
Err(e) => {
|
||||
throw_error(&context, e);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
throw_error(&context, e);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn source_mapper(
|
||||
ctx: *mut sys::JSContext,
|
||||
opaque: *mut std::os::raw::c_void,
|
||||
file: u32,
|
||||
line: i32,
|
||||
pfile: *mut u32,
|
||||
pline: *mut i32,
|
||||
) {
|
||||
let ctx = ContextRef::from_raw(ctx);
|
||||
let file = AtomRef::from_raw(file, &ctx);
|
||||
|
||||
let loader = unsafe {
|
||||
let ptr = opaque as *const RefCell<PrivateState>;
|
||||
ptr.as_ref()
|
||||
.expect("We already know this runtime is one of ours!")
|
||||
.borrow()
|
||||
.loader
|
||||
.clone()
|
||||
};
|
||||
|
||||
let result = {
|
||||
let loader = loader.borrow();
|
||||
loader.map_source(&ctx, &file, line)
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok((file, line)) => {
|
||||
*pfile = Atom::consume(file);
|
||||
*pline = line;
|
||||
}
|
||||
Err(e) => {
|
||||
throw_error(&ctx, e);
|
||||
*pfile = file.atom;
|
||||
*pline = line;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn promise_rejection_tracker(
|
||||
|
|
@ -171,7 +228,17 @@ impl Runtime {
|
|||
T: ModuleLoader + 'static,
|
||||
{
|
||||
let mut state = unsafe { PrivateState::from_rt_mut(self.rt) };
|
||||
state.loader = Arc::new(Box::new(loader));
|
||||
if loader.support_source_map() {
|
||||
unsafe {
|
||||
let opaque = sys::JS_GetRuntimeOpaque(self.rt);
|
||||
sys::JS_SetSourceMapFunc(self.rt, Some(PrivateState::source_mapper), opaque);
|
||||
}
|
||||
} else {
|
||||
unsafe {
|
||||
sys::JS_SetSourceMapFunc(self.rt, None, std::ptr::null_mut());
|
||||
}
|
||||
}
|
||||
state.loader = Arc::new(RefCell::new(Box::new(loader)));
|
||||
}
|
||||
|
||||
/// Set a tracker to be notified whenever a promise is rejected. By
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue