Add claude docs
This commit is contained in:
@@ -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`
|
||||
Reference in New Issue
Block a user