# w3m JavaScript Integration: Comprehensive Implementation Plan ## Executive Summary This document provides a detailed implementation roadmap for adding JavaScript support to w3m, a text-based web browser. The integration focuses on essential web functionality while maintaining w3m's lightweight nature and terminal-based interface. **FEASIBILITY ASSESSMENT: CHALLENGING BUT ACHIEVABLE** Adding JavaScript to w3m is ambitious but technically feasible with careful planning and phased implementation. The key is balancing functionality with w3m's core philosophy of being a lightweight, fast, text-based browser. --- ## 1. ARCHITECTURE ANALYSIS: W3M CODEBASE STRUCTURE ### Current w3m Architecture w3m's architecture provides several integration points for JavaScript: #### Core Data Structures (fm.h:455-522) ```c typedef struct _Buffer { Line *firstLine, *topLine, *currentLine, *lastLine; // Document structure AnchorList *href, *name, *img, *formitem; // Interactive elements FormList *formlist; // Forms ParsedURL currentURL, *baseURL; // Navigation // ... 70+ additional fields } Buffer; typedef struct _Line { // Text line representation char *lineBuf; // Text content Lineprop *propBuf; // Character properties Linecolor *colorBuf; // Color information (if USE_ANSI_COLOR) // Position and formatting data } Line; ``` #### HTML Processing Pipeline (file.c) 1. **HTML Parsing**: `loadGeneralFile()` → `loadHTMLBuffer()` → HTML tag processing 2. **Document Building**: `struct readbuffer` → `flushline()` → Buffer/Line creation 3. **Rendering**: `displayBuffer()` → terminal output #### Event System (main.c:1300) - **Input Processing**: `keyPressEventProc()` handles all user input - **Event Loop**: `getch()` → keymap lookup → function dispatch - **Form Interaction**: Form elements trigger buffer modifications ### Integration Points for JavaScript 1. **HTML Tag Processing** (parsetagx.c): Hook JavaScript parsing into HTML_SCRIPT tags 2. **Buffer Management** (buffer.c): Extend Buffer structure for DOM representation 3. **Event System** (main.c): Integrate JS event handlers into existing input system 4. **Form Processing** (form.c): Connect JS to form validation and submission 5. **Network Layer** (file.c): Handle XMLHttpRequest and fetch operations --- ## 2. JAVASCRIPT ENGINE RECOMMENDATION: QuickJS ### Selected Engine: QuickJS - **Rationale**: 367kB footprint, ES2023 compliance, MIT license compatibility - **Integration**: Drop-in C files with clean API - **Performance**: Excellent balance for text browser needs ### QuickJS Integration Plan ```c // Core JavaScript context structure typedef struct { JSRuntime *runtime; JSContext *context; JSValue global_obj; JSValue document_obj; JSValue window_obj; } W3MJSContext; // Per-buffer JavaScript state typedef struct { W3MJSContext *js_ctx; JSValue *script_objects; // Array of script element objects int script_count; char *pending_scripts; // Scripts to execute on load } BufferJSState; ``` --- ## 3. DOM REPRESENTATION REQUIREMENTS ### Minimal DOM Implementation w3m needs a simplified DOM focused on essential web functionality: #### Core DOM Objects ```c // Document Object Model structures typedef struct W3MElement { char *tagName; // Element tag name char *id; // Element ID char *className; // CSS classes struct W3MElement *parent; // Parent element struct W3MElement *firstChild; struct W3MElement *nextSibling; // w3m-specific mappings Line *line; // Associated line in buffer int line_pos; // Position within line Anchor *anchor; // If element is interactive FormItem *form_item; // If element is form control // Attributes and content HashMap *attributes; char *textContent; char *innerHTML; } W3MElement; typedef struct W3MDocument { W3MElement *documentElement; // element W3MElement *body; //
element W3MElement *head; // element Buffer *buffer; // Associated w3m buffer char *title; char *URL; } W3MDocument; ``` #### DOM-to-Buffer Mapping - **Element-to-Line Mapping**: Each DOM element maps to specific Line/position - **Dynamic Updates**: Changes to DOM trigger buffer regeneration - **Interactive Elements**: Form controls and links maintain two-way sync ### Essential DOM APIs 1. **Element Selection**: `getElementById()`, `getElementsByTagName()` 2. **Content Manipulation**: `innerHTML`, `textContent`, `setAttribute()` 3. **Form Access**: `document.forms[]`, form validation 4. **Navigation**: `location.href`, `location.reload()` --- ## 4. EVENT HANDLING INTEGRATION ### Event System Architecture ```c typedef struct W3MJSEvent { char *type; // "click", "submit", "load", etc. W3MElement *target; // Target element JSValue callback; // JavaScript callback function struct W3MJSEvent *next; // Linked list } W3MJSEvent; typedef struct { W3MJSEvent *event_listeners; // Registered event listeners int event_queue_size; W3MJSEvent **event_queue; // Pending events for processing } W3MEventSystem; ``` ### Event Integration Points #### 1. Form Events (form.c integration) ```c // In form submission handling void processFormSubmit(Buffer *buf, FormList *form) { // Existing form processing... // NEW: Fire JavaScript submit event if (buf->js_state && buf->js_state->js_ctx) { fireJSEvent(buf->js_state->js_ctx, "submit", form->target_element); } // Continue with normal submission if not prevented } ``` #### 2. Click Events (main.c:keyPressEventProc integration) ```c // In anchor click processing void followAnchor(Anchor *anchor) { // NEW: Check for JavaScript click handlers if (anchor->element && hasJSEventListener(anchor->element, "click")) { JSValue result = fireJSEvent(js_ctx, "click", anchor->element); if (JSEventDefaultPrevented(result)) { return; // Don't follow link if preventDefault() called } } // Existing anchor following logic... } ``` #### 3. Page Load Events ```c // In buffer loading completion void completeBufferLoad(Buffer *buf) { // Existing completion logic... // NEW: Execute pending scripts and fire load event if (buf->js_state) { executeBufferScripts(buf); fireJSEvent(buf->js_state->js_ctx, "load", buf->js_document->body); } } ``` --- ## 5. JAVASCRIPT-HTML BRIDGE ARCHITECTURE ### Bridge Implementation Strategy #### 1. HTML Script Tag Processing ```c // Enhanced script tag handler in parsetagx.c void processScriptTag(struct parsed_tag *tag, Buffer *buf) { char *src = tag->value[ATTR_SRC]; char *script_content = NULL; if (src) { // External script - fetch via existing URL loading script_content = loadExternalScript(src, buf); } else { // Inline script - extract from HTML content script_content = extractInlineScript(tag); } if (script_content) { addPendingScript(buf->js_state, script_content); } } ``` #### 2. DOM Object Binding ```c // Bind w3m objects to JavaScript context void bindDOMObjects(W3MJSContext *js_ctx, Buffer *buf) { // Create document object JSValue document = JS_NewObject(js_ctx->context); // Bind document methods JS_SetPropertyStr(js_ctx->context, document, "getElementById", JS_NewCFunction(js_ctx->context, js_getElementById, "getElementById", 1)); JS_SetPropertyStr(js_ctx->context, document, "createElement", JS_NewCFunction(js_ctx->context, js_createElement, "createElement", 1)); // Bind to global object JS_SetPropertyStr(js_ctx->context, js_ctx->global_obj, "document", document); // Create window object with location JSValue window = JS_NewObject(js_ctx->context); JSValue location = JS_NewObject(js_ctx->context); JS_SetPropertyStr(js_ctx->context, location, "href", JS_NewString(js_ctx->context, buf->currentURL.url)); JS_SetPropertyStr(js_ctx->context, window, "location", location); JS_SetPropertyStr(js_ctx->context, js_ctx->global_obj, "window", window); } ``` #### 3. Form Integration Bridge ```c // JavaScript form validation integration JSValue js_validateForm(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { // Get form reference from arguments FormList *form = getFormFromJSValue(ctx, argv[0]); // Perform validation int valid = validateFormData(form); return JS_NewBool(ctx, valid); } ``` ### Network Integration ```c // Simple XMLHttpRequest implementation using w3m's existing network layer JSValue js_fetch(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { const char *url = JS_ToCString(ctx, argv[0]); // Use w3m's existing loadGeneralFile for HTTP requests URLFile *response = loadURL(url, current_buffer); // Convert response to JavaScript Promise/response object JSValue result = createJSResponse(ctx, response); JS_FreeCString(ctx, url); return result; } ``` --- ## 6. IMPLEMENTATION ROADMAP ### Phase 1: Foundation (Months 1-2) **Goal**: Basic JavaScript execution infrastructure #### Milestones: 1. **QuickJS Integration** - Add QuickJS source files to w3m build system - Modify configure.ac and Makefile for conditional compilation - Create basic JavaScript context management 2. **Buffer Extension** - Extend Buffer structure with JavaScript state - Add memory management for JS contexts - Implement cleanup in buffer destruction 3. **Script Tag Recognition** - Modify HTML parser to recognize `