Add claude docs

This commit is contained in:
2026-06-16 10:15:59 -05:00
parent 8131bcd4d4
commit ed5c60ac30
32 changed files with 3781 additions and 13 deletions
+167
View File
@@ -0,0 +1,167 @@
# Script System (JerryScript)
Source: `src/dusk/script/`, modules at `src/dusk/script/module/`
## Overview
The engine embeds **JerryScript** as its scripting runtime. Game scenes
and logic are authored in JavaScript (ES5 subset). The script system
initialises JerryScript, registers all built-in C modules as JS globals,
and runs the event loop each tick.
The full rules for writing JS asset scripts are in `CLAUDE.md` under
"JavaScript (asset scripts)". This doc covers the C-side module system.
## Script lifecycle
```c
errorret_t scriptInit(); // start JerryScript, register all modules
errorret_t scriptUpdate(); // run pending microjobs (call once per frame)
errorret_t scriptDispose(); // shut down JerryScript
errorret_t scriptExecString(const char_t *source);
// Evaluate a JS source string in global scope.
errorret_t scriptExecFile(const char_t *path);
// Load + eval a script from the asset archive. Result cached by asset
// system -- repeated calls with the same path do not re-execute.
```
## Module registration
All C modules are initialised in `src/dusk/script/module/modulelist.c`:
```c
void moduleListInit(void); // called by scriptInit
void moduleListDispose(void); // called by scriptDispose
```
Each module's `Init` is called once. The module registers its
properties and methods on `scriptproto_t` objects (see below), which
become JS globals.
## Writing a C module -- the `scriptproto_t` pattern
A `scriptproto_t` represents a JS class prototype backed by a C struct.
### 1. Declare in the header
```c
// moduleMything.h
extern scriptproto_t MODULE_MYTHING_PROTO;
// Init and dispose for the module itself:
void moduleMyThingInit(void);
void moduleMyThingDispose(void);
```
### 2. Implement
```c
// moduleMything.c
scriptproto_t MODULE_MYTHING_PROTO;
// JS-callable function using the convenience macro:
moduleBaseFunction(myThingDoSomething) {
moduleBaseRequireArgs(1);
moduleBaseRequireNumber(0);
float_t x = moduleBaseArgFloat(0);
// ... do work ...
return jerry_undefined();
}
void moduleMyThingInit(void) {
scriptProtoInit(
&MODULE_MYTHING_PROTO,
"MyThing", // JS global name; NULL to skip registration
sizeof(mything_t),
myThingCtor // constructor handler, or NULL
);
// Instance methods:
scriptProtoDefineFunc(
&MODULE_MYTHING_PROTO, "doSomething", myThingDoSomething
);
// Instance property (get/set):
scriptProtoDefineProp(
&MODULE_MYTHING_PROTO, "x", myThingGetX, myThingSetX
);
// Static method:
scriptProtoDefineStaticFunc(
&MODULE_MYTHING_PROTO, "create", myThingCreate
);
}
```
### 3. Register
In `modulelist.c`: `#include` the header and call `moduleMyThingInit()`
in `moduleListInit()` (and `Dispose` in `moduleListDispose()`).
## `moduleBaseFunction` macro
```c
moduleBaseFunction(myFn) {
// callInfo, args[], argc available
moduleBaseRequireArgs(2);
moduleBaseRequireNumber(0);
moduleBaseRequireString(1);
float_t x = moduleBaseArgFloat(0);
int32_t n = moduleBaseArgInt(0);
bool_t b = moduleBaseArgBool(0);
float_t opt = moduleBaseOptFloat(2, 0.0f); // optional with default
// Error propagation:
errorret_t ret = someCall();
if(errorIsNotOk(ret)) return moduleBaseThrowError(ret);
return jerry_undefined(); // or jerry_boolean(true) etc.
}
```
## Wrapping C values in JS objects
```c
// Create a JS object wrapping a copy of a C value:
jerry_value_t obj = scriptProtoCreateValue(&MY_PROTO, &myValue);
// Unwrap back to C pointer:
mything_t *ptr = scriptProtoGetValue(&MY_PROTO, jsObj);
// ptr is NULL if jsObj is not an instance of MY_PROTO.
```
## Utility helpers (`modulebase.h`)
| Helper | Purpose |
|--------|---------|
| `moduleBaseThrow(msg)` | Return a JS TypeError |
| `moduleBaseThrowError(ret)` | Convert `errorret_t` -> JS error |
| `moduleBaseToString(val, buf, len)` | Jerry value -> C string |
| `moduleBaseGetProp(obj, name)` | Get object property by name |
| `moduleBaseWrapPointer(ptr)` | Wrap a raw pointer in a JS object |
| `moduleBaseUnwrapPointer(val)` | Unwrap a raw pointer |
| `moduleBaseSetValue(name, val)` | Set a global JS variable |
| `moduleBaseSetNumber(name, n)` | Set a global JS number |
| `moduleBaseSetInt(name, n)` | Set a global JS integer |
| `moduleBaseDefineMethod(obj, name, fn)` | Add method to any JS object |
| `moduleBaseDefineGlobalMethod(name, fn)` | Add method to global scope |
## Async JS -- pending promises (`scriptpromisepend.h`)
When a C module needs to resolve a JS `Promise` from an asynchronous
C event, use `scriptpromisepend_t`. Each module declares a fixed-size
pending slot array; the helpers add/resolve/reject by an opaque key.
Full API and design notes: `.claude/script-promises.md`
## Type declarations (`.d.ts`)
Every module that is accessible from JS **must** have a corresponding
TypeScript declaration file in `types/`. The CLAUDE.md checklist
requires updating these whenever a `.c` module file changes.
- Add `types/<category>/mymod.d.ts`
- Add `/// <reference path="..." />` to `types/index.d.ts`