[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,11 +1,12 @@
|
|||
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
|
||||
use oden_js::{
|
||||
module::loader::{ModuleLoader, ModuleSource},
|
||||
Context, ContextRef, RejectedPromiseTracker, Result, Runtime, Value,
|
||||
Atom, Context, ContextRef, RejectedPromiseTracker, Result, Runtime, Value,
|
||||
};
|
||||
use sourcemap::SourceMap;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsStr;
|
||||
use std::sync::mpsc::{channel, Receiver, Sender};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
use tracy_client::span;
|
||||
use winit::event::*;
|
||||
|
|
@ -21,36 +22,66 @@ mod typescript;
|
|||
use typescript::transpile_to_javascript;
|
||||
|
||||
struct Loader {
|
||||
watcher: Arc<Mutex<RecommendedWatcher>>,
|
||||
watcher: RecommendedWatcher,
|
||||
source_map: HashMap<Atom, SourceMap>,
|
||||
}
|
||||
|
||||
impl Loader {
|
||||
pub fn new(reload_trigger: Sender<()>) -> Loader {
|
||||
let watcher = Arc::new(Mutex::new(
|
||||
notify::recommended_watcher(move |_| {
|
||||
Loader {
|
||||
watcher: notify::recommended_watcher(move |_| {
|
||||
let _ = reload_trigger.send(());
|
||||
})
|
||||
.expect("Unable to create watcher"),
|
||||
));
|
||||
Loader { watcher }
|
||||
source_map: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleLoader for Loader {
|
||||
fn load(&self, _context: &ContextRef, name: &str) -> Result<ModuleSource> {
|
||||
fn load<'a>(&mut self, context: &'a ContextRef, name: &str) -> Result<ModuleSource<'a>> {
|
||||
eprintln!("Loading {name}...");
|
||||
let path = io::resolve_path(name, &["ts"])?;
|
||||
let contents = std::fs::read_to_string(&path)?;
|
||||
let contents = if path.extension().and_then(OsStr::to_str) == Some("ts") {
|
||||
transpile_to_javascript(name, contents)?
|
||||
let (c, sm) = transpile_to_javascript(name, contents)?;
|
||||
let a = context.new_atom(name)?;
|
||||
self.source_map.insert(a, sm);
|
||||
c
|
||||
} else {
|
||||
contents
|
||||
};
|
||||
|
||||
let mut watcher = self.watcher.lock().unwrap();
|
||||
let _ = watcher.watch(&path, RecursiveMode::NonRecursive);
|
||||
let _ = self.watcher.watch(&path, RecursiveMode::NonRecursive);
|
||||
Ok(ModuleSource::JavaScript(contents))
|
||||
}
|
||||
|
||||
fn support_source_map(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn map_source(
|
||||
&self,
|
||||
context: &ContextRef,
|
||||
file: &oden_js::AtomRef,
|
||||
line: i32,
|
||||
) -> Result<(Atom, i32)> {
|
||||
let file = file.dup(&context);
|
||||
|
||||
// Yuck.
|
||||
if let Ok(line) = line.try_into() {
|
||||
if let Some(sm) = self.source_map.get(&file) {
|
||||
if let Some(token) = sm.lookup_token(line, 0) {
|
||||
if let Ok(src_line) = token.get_src_line().try_into() {
|
||||
return Ok((file, src_line));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eprintln!("Not mapped");
|
||||
Ok((file, line))
|
||||
}
|
||||
}
|
||||
|
||||
struct RejectedPromiseHandler {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use deno_ast::{parse_module, MediaType, ParseParams, SourceTextInfo};
|
||||
use oden_js::{Error, Result};
|
||||
use sourcemap::SourceMap;
|
||||
|
||||
pub fn transpile_to_javascript(path: &str, input: String) -> Result<String> {
|
||||
pub fn transpile_to_javascript(path: &str, input: String) -> Result<(String, SourceMap)> {
|
||||
let text_info = SourceTextInfo::new(input.into());
|
||||
let parsed_source = parse_module(ParseParams {
|
||||
specifier: path.to_string(),
|
||||
|
|
@ -25,9 +26,18 @@ pub fn transpile_to_javascript(path: &str, input: String) -> Result<String> {
|
|||
)
|
||||
})?;
|
||||
|
||||
let options: deno_ast::EmitOptions = Default::default();
|
||||
let options = deno_ast::EmitOptions {
|
||||
inline_source_map: false,
|
||||
source_map: true,
|
||||
..Default::default()
|
||||
};
|
||||
let transpiled = parsed_source
|
||||
.transpile(&options)
|
||||
.map_err(|e| Error::ParseError(path.into(), e.to_string()))?;
|
||||
return Ok(transpiled.text);
|
||||
|
||||
let source_map = transpiled.source_map.unwrap();
|
||||
let bytes = source_map.into_bytes();
|
||||
let source_map = SourceMap::from_slice(&bytes).expect("unable to parse source map");
|
||||
|
||||
return Ok((transpiled.text, source_map));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue