browser_engine 0.1.0

A modular, GPU-accelerated, security-first web browser engine built from scratch in Rust.
Documentation
use crate::dom::{Dom, NodeType};
use super::bytecode::{Compiler, Value};
use super::lexer::JsLexer;
use super::parser::JsParser;
use super::vm::VM;

pub fn execute_js_on_dom(script: &str, dom: &mut Dom) {
    let tokens = JsLexer::new(script).tokenize();
    let program = JsParser::new(tokens).parse();
    let chunk = Compiler::new().compile(&program);

    let mut vm = VM::new();
    let dom_ptr_val = dom as *mut Dom as usize;

    vm.register_native_fn("addEventListener", move |_vm, args| {
        if args.len() >= 2 {
            println!("JS Event: Registered listener for '{}'", args[0].to_string());
        }
        Value::Undefined
    });

    vm.register_native_fn("setTimeout", move |_vm, args| {
        if args.len() >= 2 {
            println!("JS Timer: Scheduled callback for {} ms", args[1].to_string());
        }
        Value::Number(1.0)
    });

    vm.register_native_fn("fetch", move |_vm, args| {
        if !args.is_empty() {
            let url = args[0].to_string();
            println!("JS fetch API requested: {}", url);
            if let Ok(resp) = crate::net::fetch(&url) {
                return Value::String(resp.body_as_string());
            }
        }
        Value::Undefined
    });

    vm.register_native_fn("getContext", move |_vm, args| {
        if !args.is_empty() && args[0].to_string() == "2d" {
            println!("Canvas 2D: Context 2D initialized");
            return Value::String("CanvasRenderingContext2D".to_string());
        }
        Value::Undefined
    });

    vm.register_native_fn("fillRect", move |_vm, args| {
        if args.len() >= 4 {
            println!(
                "Canvas 2D fillRect(x={}, y={}, w={}, h={})",
                args[0].to_string(),
                args[1].to_string(),
                args[2].to_string(),
                args[3].to_string()
            );
        }
        Value::Undefined
    });

    vm.register_native_fn("Worker", move |_vm, args| {
        if !args.is_empty() {
            let script_url = args[0].to_string();
            println!("WebWorker: Spawning worker thread for {}", script_url);
            return Value::String(format!("Worker({})", script_url));
        }
        Value::Undefined
    });

    vm.register_native_fn("postMessage", move |_vm, args| {
        if !args.is_empty() {
            println!("WebWorker postMessage: {}", args[0].to_string());
        }
        Value::Undefined
    });

    vm.register_native_fn("setElementText", move |_vm, args| {
        if args.len() >= 2 {
            let target_id = args[0].to_string();
            let new_text = args[1].to_string();
            unsafe {
                let dom_ref = &mut *(dom_ptr_val as *mut Dom);
                for i in 0..dom_ref.nodes.len() {
                    let is_match = match &dom_ref.nodes[i].node_type {
                        NodeType::Element(el) => el.id.as_deref() == Some(&target_id),
                        _ => false,
                    };
                    if is_match {
                        if !dom_ref.nodes[i].children.is_empty() {
                            let child_idx = dom_ref.nodes[i].children[0];
                            dom_ref.nodes[child_idx].node_type = NodeType::Text(new_text.clone());
                        } else {
                            let new_idx = dom_ref.nodes.len();
                            dom_ref.nodes.push(crate::dom::DomNode {
                                node_type: NodeType::Text(new_text.clone()),
                                parent: Some(i),
                                children: vec![],
                            });
                            dom_ref.nodes[i].children.push(new_idx);
                        }
                        break;
                    }
                }
            }
        }
        Value::Undefined
    });

    vm.run(&chunk);
}