# Kernel Javascript support

This document details the kernel javascript debugging extension recently added to the reactos kernel.

## Enabling

The extension is enabled when KDBG := 1 is set in config in the reactos source tree.
kdb presents the usual prompt when ReactOS starts, but the 'js' command initializes the javascript system and allows the user to start working with the system in javascript. A welcome banner is displayed when the system is ready, along with the prompt kjs:>.

## Using

You may type as many lines in each input as needed. To cancel some input, just enter '.' as the only character on an input line. To exit from the javascript interpreter, enter '.' on the first input line. In order to determine when the user is finished typing, the kernel javascript system uses the harmless ';;' sequence. Entering ';;' anywhere in the input terminates input and evaluates the current input buffer. The buffer is emptied afterward. Any javascript error messages or output are printed before the next prompt is displayed. Note that the interpreter does not automatically print the evaluation results, so it's useful to wrap simple evaluations with write().

## Sample Session

    kdb:> js
    JS Registry Init Complete.  Welcome to ReactOS kernel scripting
    Kernel Debugger Script Interface (JavaScript :-)
    Terminate input with ;; and end scripting with .
    kjs:> write(System.getmodule(1));;
    hal.dll,3225501696
    kjs:> write(System.getmodule(1)[1].toString(16));;
    c0414000
    kjs:> write(ebp().toString(16));;
    cee8bf84

    kjs:> function dump_sec(base) {
    .....   base2 = peekw(base + 0x3c) + base;
    .....   sec_off = 0xf8;
    .....   for( i = 0; peekl(base2 + sec_off + (40 * i)); i++ ) {
    .....     base_sec = base2 + sec_off + (40 * i);
    .....     write("Section: " + System.mread(0,base_sec) + "\n");
    .....     write("RVA:     " + peekl(base_sec + 12).toString(16) + "\n");
    .....   }
    ..... }
    ..... ;;
    kjs:> dump_sec(0xc0000000);;
    Section: .text
    RVA:     1000
    Section: init
    RVA:     e6000
    Section: .data
    RVA:     f4000
    Section: .edata
    RVA:     10d000
    Section: .idata
    RVA:     115000
    Section: .rsrc
    RVA:     116000
    Section: .bss
    RVA:     118000
    Section: .reloc
    RVA:     15a000

    kjs:> var key = "\\registry\\machine\\system\\currentcontrolset\\services\\ne20001\\parameters\\tcpip";;
    kjs:> write(regread(key,"defaultgateway"));;
    10.0.0.1

## Builtin and initialized functions

These functions are available after a successful javascript initialization:
System.getmodule(n) => (string,int) array
Returns the name and base address of the nth module in the kernel module list.
System.mread(s,address) => integer/string
System.mread reads a value from memory and returns it. s determines what type of read is performed, and address specifies the starting address of the operation.
Valid values of s are:
0 -- Read a null-terminated ascii string
1 -- Read a byte
2 -- Read a word
4 -- Read a dword
System.mwrite(s,address,value) => bool
System.mwrite writes a value to a memory address. The operand size depends on s, 1 for byte, 2 for word, 4 for dword.
System.print(...) => undefined
Uses DbgPrint to print the specified output. In javascript, every value is printable, so feel free to give any value type to print.
Use C style escapes for tabs and newlines: \t and \n.
System.regs(int) => int
System.regs read the specified word value from the TRAP_FRAME given to kdb when it was started. This is useful for locating the stack, along with various other queries. The machine registers are also provided as named functions by javascript, for example ebp() and eax().
System.regread(key,value) => string/undefined
System.regread reads a string value from the registry (as a member of the specified registry key). If the read is successful, the string value contained in it is returned. If the value cannot be read, then undefined is returned.
This method is used by the registry initializer to read the initialization strings.
ebp(), eip(), esp() ... vm86_gs() => int
Every register provided by the system trap frame is available as a global function of the same name. This makes reading specific registers easy.
peek,peekw,peekl(int addr) => int
Aliases for System.mread([1,2,4],addr)
poke,pokew,pokel(int addr, int value) => int
Aliases for System.mwrite([1,2,4],addr,value)
write(...) => undefined
Alias for System.print