diff --git a/oden-js-sys/quickjs/quickjs.c b/oden-js-sys/quickjs/quickjs.c index 505f27dd..f7033f31 100644 --- a/oden-js-sys/quickjs/quickjs.c +++ b/oden-js-sys/quickjs/quickjs.c @@ -1018,11 +1018,6 @@ typedef struct JSBreakpoint { JS_BOOL enabled; } JSBreakpoint; -typedef struct JSDebugContext { - JSContext *ctx; - JSStackFrame *sf; -} JSDebugContext; - static int JS_InitAtoms(JSRuntime *rt); static JSAtom __JS_NewAtomInit(JSRuntime *rt, const char *str, int len, int atom_type); @@ -6508,7 +6503,6 @@ static void get_frame_debug_position(JSContext *ctx, JSStackFrame *sf, *backtrace_barrier = FALSE; *function = get_func_name(ctx, sf->cur_func); - p = JS_VALUE_GET_OBJ(sf->cur_func); if (js_class_has_bytecode(p->class_id)) { JSFunctionBytecode *b; @@ -6516,6 +6510,7 @@ static void get_frame_debug_position(JSContext *ctx, JSStackFrame *sf, b = p->u.func.function_bytecode; *backtrace_barrier = b->backtrace_barrier; + *function = JS_AtomToCString(ctx, b->func_name); if (b->has_debug) { line_num1 = find_line_num(ctx, b, sf->cur_pc - b->byte_code_buf - 1); @@ -33780,24 +33775,6 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, goto fail1; fun_obj = JS_DupValue(ctx, JS_MKPTR(JS_TAG_MODULE, m)); } - - if (ctx->rt->debug_callback) { - JSDebugContext dctx; - dctx.ctx = ctx; - dctx.sf = sf; - - JSDebugEvent evt; - evt.reason = JS_BREAK_CODE_LOADED; - evt.u.loaded.filename = filename; - - /* TODO: Handle the step/resume/what-have-you. Step from here will - be complicated because the function we need to step into will be - the one we just parsed, kinda- unless it's a module? Even then - it's not clear where the break will go if we're loading a - module... yikes. */ - /* resume = */ctx->rt->debug_callback(&dctx, &evt, ctx->rt->debug_opaque); - } - if (flags & JS_EVAL_FLAG_COMPILE_ONLY) { ret_val = fun_obj; } else { @@ -54170,12 +54147,6 @@ void JS_SetSourceMapFunc(JSRuntime *rt, JSMapSourceFunc *map_func, void *opaque) /* Debugger */ -void JS_SetDebugCallbackFunc(JSRuntime *rt, JSDebugCallbackFunc *func, void *opaque) -{ - rt->debug_callback = func; - rt->debug_opaque = opaque; -} - static BOOL find_pc_offset(JSFunctionBytecode *b, int target_line, int *break_pc, int *actual_line) { const uint8_t *p_end, *p; @@ -54228,8 +54199,7 @@ static BOOL find_pc_offset(JSFunctionBytecode *b, int target_line, int *break_pc return FALSE; } -static JSBreakpoint *find_existing_breakpoint(JSContext *ctx, JSFunctionBytecode *func, int pc) -{ +static JSBreakpoint *find_existing_breakpoint(JSContext *ctx, JSFunctionBytecode *func, int pc) { struct list_head *el; list_for_each(el, &ctx->rt->breakpoint_list) { JSBreakpoint *bp = list_entry(el, JSBreakpoint, link); @@ -54240,8 +54210,12 @@ static JSBreakpoint *find_existing_breakpoint(JSContext *ctx, JSFunctionBytecode return NULL; } -static int js_handle_breakpoint(JSContext *ctx, JSFunctionBytecode *b, int code_offset) -{ +typedef struct JSDebugContext { + JSContext *ctx; + JSStackFrame *sf; +} JSDebugContext; + +static int js_handle_breakpoint(JSContext *ctx, JSFunctionBytecode *b, int code_offset) { int next_op; /* JSResumeMode resume = JS_RESUME_MODE_CONTINUE; */ JSRuntime *rt = ctx->rt; @@ -54253,11 +54227,7 @@ static int js_handle_breakpoint(JSContext *ctx, JSFunctionBytecode *b, int code_ dctx.ctx = ctx; dctx.sf = ctx->rt->current_stack_frame; - JSDebugEvent evt; - evt.reason = JS_BREAK_BREAKPOINT; - evt.u.breakpoint = bp; - - /* resume = */rt->debug_callback(&dctx, &evt, rt->debug_opaque); + /* resume = */rt->debug_callback(&dctx, JS_BREAK_BREAKPOINT, bp, rt->debug_opaque); } } next_op = bp->replaced_byte; @@ -54271,11 +54241,8 @@ static int js_handle_breakpoint(JSContext *ctx, JSFunctionBytecode *b, int code_ JSDebugContext dctx; dctx.ctx = ctx; dctx.sf = ctx->rt->current_stack_frame; - - JSDebugEvent evt; - evt.reason = JS_BREAK_STEP; - /* resume = */rt->debug_callback(&dctx, &evt, rt->debug_opaque); + /* resume = */rt->debug_callback(&dctx, JS_BREAK_STEP, NULL, rt->debug_opaque); } } @@ -54304,7 +54271,7 @@ void JS_DebugGetFrameSourcePosition(JSDebugContext *dctx, JSDebugFrame *frame, JSStackFrame *sf = (JSStackFrame *)frame; JSContext *ctx = dctx->ctx; BOOL backtrace_barrier; - + get_frame_debug_position(ctx, sf, function, file, line, &backtrace_barrier); } diff --git a/oden-js-sys/quickjs/quickjs.h b/oden-js-sys/quickjs/quickjs.h index 7d9faf31..6ca6cec7 100644 --- a/oden-js-sys/quickjs/quickjs.h +++ b/oden-js-sys/quickjs/quickjs.h @@ -1070,25 +1070,15 @@ typedef enum JSResumeMode { } JSResumeMode; typedef enum JSBreakReason { - JS_BREAK_CODE_LOADED, JS_BREAK_BREAKPOINT, JS_BREAK_STEP, } JSBreakReason; typedef struct JSBreakpoint JSBreakpoint; -typedef struct JSDebugEvent { - JSBreakReason reason; - union { - struct { - const char *filename; - } loaded; - JSBreakpoint *breakpoint; - } u; -} JSDebugEvent; - typedef JSResumeMode JSDebugCallbackFunc(JSDebugContext *ctx, - JSDebugEvent *event, + JSBreakReason reason, + JSBreakpoint *breakpoint, void *opaque); void JS_SetDebugCallbackFunc(JSRuntime *rt, JSDebugCallbackFunc *bp_func, void *opqaue); diff --git a/src/lib.rs b/src/lib.rs index d0d86d4f..72e6c69f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1376,8 +1376,6 @@ fn main_thread(event_loop: EventLoopProxy, state: State, reciever: Re let mut script = script::ScriptContext::new(None, script_reload_send.clone()) .expect("Unable to create initial script context"); - let _debugger = script::debugger::start_debugger(); - const SPF: f64 = 1.0 / 60.0; loop { frame_mark(); diff --git a/src/script.rs b/src/script.rs index 81b9faf9..ac9905b4 100644 --- a/src/script.rs +++ b/src/script.rs @@ -11,7 +11,6 @@ use std::time::Instant; use tracy_client::span; use winit::event::*; -pub mod debugger; pub mod graphics; mod input; mod io; diff --git a/src/script/debugger.rs b/src/script/debugger.rs deleted file mode 100644 index 4f5a5c3a..00000000 --- a/src/script/debugger.rs +++ /dev/null @@ -1,139 +0,0 @@ -use std::collections::HashMap; -use std::io; -use std::io::{BufRead, BufReader, Write}; -use std::net::{TcpListener, TcpStream}; -use std::thread; - -pub struct Debugger { - _thread: thread::JoinHandle<()>, -} - -fn write_http_response( - stream: &mut TcpStream, - code: u16, - phrase: &str, - content_type: &str, - data: &[u8], -) -> io::Result<()> { - let length = data.len(); - let buffer = format!( - "HTTP/1.1 {code} {phrase}\r\n\ - content-length: {length}\r\n\ - content-type: {content_type}\r\n\ - \r\n" - ); - stream.write_all(buffer.as_bytes())?; - stream.write_all(data) -} - -fn write_http_error(stream: &mut TcpStream, code: u16, phrase: &str) -> io::Result<()> { - write_http_response(stream, code, phrase, "text/plain", phrase.as_bytes()) -} - -fn write_http_ok(stream: &mut TcpStream, content_type: &str, data: &[u8]) -> io::Result<()> { - write_http_response(stream, 200, "OK", content_type, data) -} - -fn handle_connection(mut stream: TcpStream) -> io::Result<()> { - let mut buf_reader = BufReader::new(&mut stream); - - let mut buffer = String::new(); - buf_reader.read_line(&mut buffer)?; - - let parts: Vec<_> = buffer.trim().split(" ").collect(); - if parts.len() != 3 { - eprintln!("Invalid request line: {buffer}"); - write_http_error(&mut stream, 400, "Invalid request")?; - return Ok(()); - } - - let method = parts[0]; - let path = parts[1]; - eprintln!("Debugger: {method} {path}"); - - let mut headers = HashMap::new(); - let mut header_line_buffer = String::new(); - loop { - header_line_buffer.clear(); - buf_reader.read_line(&mut header_line_buffer)?; - let header_line = header_line_buffer.trim(); - if header_line.is_empty() { - break; - } - - let sep_idx = match header_line.find(":") { - Some(idx) => idx, - None => { - write_http_error(&mut stream, 400, "Invalid request")?; - return Ok(()); - } - }; - let header = &header_line[0..sep_idx]; - let value = &header_line[sep_idx + 1..]; - eprintln!("HEADER: {header} {value}"); - headers.insert(header.trim().to_string(), value.trim().to_string()); - } - - if method == "GET" { - if path == "/json/version" { - // NOTE: Deno spits out a V8 version here but we're not running v8. - write_http_ok( - &mut stream, - "application/json", - "{\"Browser\": \"Oden/0.0.1\", \"Protocol-Version\": \"1.3\"}".as_bytes(), - )?; - } else if path == "/json" || path == "/json/list" { - // [ - // { - // "description": "deno", - // "devtoolsFrontendUrl": "devtools://devtools/bundled/js_app.html?ws=127.0.0.1:9229/ws/01b9bd23-8810-43ed-86f7-5feef5d120fa&experiments=true&v8only=true", - // "faviconUrl": "https://deno.land/favicon.ico", - // "id": "01b9bd23-8810-43ed-86f7-5feef5d120fa", - // "title": "deno - main [pid: 40483]", - // "type": "node", - // "url": "file:///Users/doty/src/ioniq/status.ts", - // "webSocketDebuggerUrl": "ws://127.0.0.1:9229/ws/01b9bd23-8810-43ed-86f7-5feef5d120fa" - // } - // ] - } else if path == "/ws/dd5cfe85-f0b1-4241-a643-8ed81e436188" { - // I don't feel like making a new guid for each thing. - // Websocket upgrade and then debugger messages. - } else { - write_http_error(&mut stream, 404, "Not Found")?; - } - } else { - write_http_error(&mut stream, 404, "Not Found")?; - } - Ok(()) -} - -pub fn debugger_listener() -> io::Result<()> { - let listener = TcpListener::bind("127.0.0.1:0")?; - let port = listener.local_addr()?.port(); - println!("Debugger listening on http://127.0.0.1:{port}"); - for stream in listener.incoming() { - let stream = match stream { - Ok(s) => s, - Err(e) => { - eprintln!("Error accepting incoming connection: {:?}", e); - continue; - } - }; - - // TODO: Thread pool extraction here. - if let Err(e) = handle_connection(stream) { - eprintln!("Error handling incoming connection: {e}"); - } - } - Ok(()) -} - -#[allow(dead_code)] -pub fn start_debugger() -> Debugger { - let thread = thread::spawn(move || { - if let Err(e) = debugger_listener() { - eprintln!("ERROR STARTING DEBUGGER: {:?}", e); - } - }); - Debugger { _thread: thread } -}