context¶
Context は YanmaJS エンジンの実行単位です。VM・グローバル環境・GC 状態を1つに束ね、スクリプトの評価からホスト関数の登録、GC 制御まで、埋め込み API のほぼすべてがこの型のメソッドとして提供されます。型定義は type、Value の生成・変換・判定は value、エラー処理は error を参照してください。
Lifecycle¶
Context.init¶
Context を初期化して返します。内部で VM・グローバルレルムを初期化します。
| 戻り値 | 説明 |
|---|---|
!*Context |
新規 Context。失敗時は error.OutOfMemory |
使用後は deinit で解放してください。
Context.initWithMemoryLimit¶
割り当て量に上限を課した Context を作ります。信頼できない JavaScript コードをサンドボックス実行する際に使います。
| 引数 | 説明 |
|---|---|
backing_allocator |
実際にメモリを確保する下位アロケータ |
max_bytes |
累計割り当てバイト数の上限 |
Context 自身を含むすべての内部割り当てがこのアロケータ経由になり、上限を超えると通常の割り当てエラーと同じ error.OutOfMemory が(スクリプト評価であれば EvalError.OutOfMemory として)返ります。現在の使用量・上限は getMemoryUsage/getMemoryLimit で取得できます。
Context.deinit¶
Context とその内部状態(VM・ホスト関数ラッパー・initWithMemoryLimit で使った上限付きアロケータなど)をすべて解放します。以後 ctx は使用できません。
Evaluation¶
Context.eval¶
JavaScript ソースコードをその場でパース・コンパイル・実行し、最後の式文の評価結果を返します。
| 戻り値 | 説明 |
|---|---|
EvalError!Value |
成功時は最後の式の値。構文エラーや実行時エラーは対応する EvalError バリアントとして返る |
例外が捕捉されずに伝播した場合は error.UncaughtException になり、例外値は getPendingException で取得します。
Context.compileScript¶
ソースコードをパース・コンパイルするが実行はしません。同じスクリプトを複数回実行したい場合や、シリアライズして永続化したい場合に使います。
| 戻り値 | 説明 |
|---|---|
EvalError!CompiledScript |
コンパイル済みのトップレベル関数。コンパイルエラーは EvalError として返る |
戻り値は Context の永続値テーブルに登録されるため、ctx が生きている限り GC で回収されません(明示的な解放 API はなく、ctx.deinit() まで保持され続けます)。
Context.serializeScript¶
compileScript/deserializeScript で得たコンパイル済みスクリプトを、独自形式のバイトコードバイナリへシリアライズします。
| 戻り値 | 説明 |
|---|---|
![]u8 |
シリアライズされたバイト列。呼び出し側が ctx.allocator.free() で解放すること |
シリアライズ形式はエンジン内部のバイトコード表現に依存しており、YanmaJS のバージョン間で互換性は保証されません。
Context.deserializeScript¶
serializeScript が出力したバイト列から CompiledScript を復元します。compileScript と同様に結果は永続値テーブルへ登録されます。パース(ソースの字句・構文解析)を経ないため、同じスクリプトを繰り返しロードする場合は compileScript より高速です。
Context.runScript¶
compileScript/deserializeScript で得たスクリプトを実行し、結果を返します。同じ CompiledScript を複数回 runScript することもできますが、トップレベルの var/let/const 宣言は実行のたびに再評価される点に注意してください。
Context.evalModule¶
ES Modules(import/export)として source を評価します。specifier はこのモジュール自身の識別子(相対 import の解決基準)として使われます。依存モジュールの解決には setModuleLoader で登録したローダーが使われます。
Context.setModuleLoader¶
evalModule 内の import 文が参照する他モジュールをホスト側から供給するためのローダーを登録します。loader の型は ModuleLoader を参照してください。未登録のまま存在しない specifier を import するとモジュール解決エラーになります。
Context.callFunction¶
JavaScript の関数値 func を Zig 側から呼び出します。func が呼び出し可能でない場合は TypeError("value is not a function")を pending exception にセットした error.RuntimeError になります。this は undefined(sloppy mode 関数では globalThis に強制)として呼ばれます。this を明示したい場合は callFunctionWithReceiver を使います。
Context.callFunctionWithReceiver¶
pub fn callFunctionWithReceiver(ctx: *Context, func: Value, receiver: Value, args: []const Value) EvalError!Value
callFunction と同じですが、this(レシーバ)に receiver を明示指定して func を呼び出します(QuickJS の JS_Call / V8 の Function::Call 相当)。sloppy mode 関数では undefined/null の receiver は globalThis に強制されます。メソッド呼び出しやイベントリスナーの this をホストから指定したいケースで使います。
Context.drainMicrotasks¶
保留中のマイクロタスクキュー(Promise の .then/.catch/.finally コールバックなど)をキューが空になるまで実行します。eval/callFunction はマイクロタスクを自動的にはドレインしないため、Promise の解決結果を JavaScript 側の状態に反映させたい場合は明示的に呼ぶ必要があります。ドレイン完了後、未処理のまま残っている reject を検出し、setUnhandledRejectionHandler で登録したハンドラへ通知します。
Globals¶
Context.getGlobal¶
現在のレルムのグローバル変数 name の値を返します。未定義なら undefined。
Context.setGlobal¶
現在のレルムのグローバル変数 name に val を設定します(存在しなければ作成)。val がオブジェクト系の値の場合、呼び出し前に GC ルートされていなくても、この呼び出しによってグローバルテーブル経由で到達可能になります(以後は GC 対象から保護されます)。
Functions¶
Context.setFunction¶
Zig で実装した HostFn をグローバル関数 name として登録します。this を受け取らないシンプルな関数向けです。
Context.makeFunction¶
this を受け取れる HostMethod をネイティブ関数 Value として作ります。setProperty/setGlobal でメソッド・グローバル関数として設定するほか、defineProperty の getter/setter に渡すとネイティブアクセサとして機能します。
戻り値は他の make* 系関数と同様に GC 未ルートです。呼び出し側は setProperty/setGlobal/defineProperty で即座にオブジェクトへ attach するか、protect/HandleScope.pin でルートしてください。attach 前に GC を誘発しうる別の割り当てを行わないよう注意してください。
Context.makeFunctionWithData¶
pub fn makeFunctionWithData(ctx: *Context, name: []const u8, func: HostMethod, data: ?*anyopaque) !Value
makeFunction と同じですが、個別のユーザーデータポインタ data を関数に紐付けます。コールバック内から value.getFunctionData で取り出せます。エンジンは data を一切解釈しません(GC 対象外・解放はホスト責任)。
Context.callFunction¶
callFunction は Evaluation を参照してください。
Context.getCurrentCallee¶
ネイティブ関数の実行中に、現在実行中の関数自身の Value を返します。HostMethod コールバック内から value.getFunctionData と組み合わせて、自身に紐付いたユーザーデータへアクセスするために使います。ネイティブ関数の実行中以外に呼んだ場合の戻り値は未規定です。
Context.setUserData / Context.getUserData¶
pub fn setUserData(ctx: *Context, data: ?*anyopaque) void
pub fn getUserData(ctx: *Context) ?*anyopaque
Context 全体に紐付くホスト専用の自由スロットです。エンジンはこの値を一切解釈せず、GC 対象にもなりません(寿命・解放はホスト側の責任)。HostMethod からレシーバ以外のホスト状態(バインディング全体など)へ到達するために使います。setUserData(ctx, null) でクリアできます。
Promises¶
Context.makePromise¶
pending 状態の Promise を新規作成します。
| 戻り値フィールド | 型 | 説明 |
|---|---|---|
promise |
Value |
作成された Promise オブジェクト(JavaScript 側に渡す用) |
handle |
PromiseHandle |
resolvePromise/rejectPromise に渡す操作用ハンドル |
promise は内部で handle 経由の PersistentHandle によってルートされているため、resolvePromise/rejectPromise を呼ぶまで GC で回収されません。
Context.resolvePromise¶
handle に対応する Promise を val で fulfill します。呼び出し後、内部で保持していたルートは解除されます(Promise 自体は他から参照されていれば生存し続けます)。実際にコールバックへ反映するには drainMicrotasks を呼ぶ必要があります。
Context.rejectPromise¶
handle に対応する Promise を理由 val で reject します。resolvePromise と同様、反映には drainMicrotasks が必要です。
Objects/Arrays¶
Context.makeObject¶
空のプレーンオブジェクト({})を作ります。戻り値は GC 未ルートです(makeFunction と同様、即座に attach するかルートしてください)。
Context.makeArray¶
空の配列([])を作ります。戻り値は GC 未ルートです。
Context.makeHostObject¶
pub fn makeHostObject(
ctx: *Context,
data: ?*anyopaque,
finalizer: ?*const fn (?*anyopaque) void,
) !Value
ホスト側データ data とファイナライザ finalizer を紐付けたプレーンオブジェクトを作ります。DOM ライクなホストオブジェクトを実装する際の基本ブロックです。
| 引数 | 説明 |
|---|---|
data |
オブジェクトに紐付けるホスト側ポインタ。value.getHostData で取り出す |
finalizer |
オブジェクトが GC で回収される際に一度だけ呼ばれる。null なら何もしない |
setPrototype と組み合わせて複数の makeHostObject 結果をプロトタイプチェーンで繋げば、多段の interface(例: Node ← Element ← HTMLElement)を構築できます。戻り値は GC 未ルートです。
Properties¶
Context.defineProperty¶
Object.defineProperty 相当の低レベル API です。desc の型・既定値は PropertyDescriptor を参照してください。obj がプレーンオブジェクトでない場合は何もしません。
Context.setProperty¶
プレーンオブジェクト obj のプロパティ name に val を設定します(writable: true, enumerable: true, configurable: true の通常のデータプロパティとして、既存プロパティがあれば値のみ更新)。obj がプレーンオブジェクトでなければ何もしません。
Context.setIndex¶
配列 arr の index 番目の要素に val を設定します。index が現在の長さ以上の場合は配列を伸張します。arr が配列でなければ何もしません。
Context.setPrototype¶
obj のプロトタイプを proto に設定します(Object.setPrototypeOf 相当)。proto が JavaScript の null ならプロトタイプチェーンを切り離します。obj がプレーンオブジェクトでない場合、または proto がプレーンオブジェクトでも null でもない場合は何もしません。
Errors¶
Context.getPendingException¶
保留中の JavaScript 例外値を返し、同時にスロットをクリアします。詳細なパターンは error を参照してください。
Context.throwValue / throwError / throwTypeError / throwRangeError / throwReferenceError / throwSyntaxError¶
pub fn throwValue(ctx: *Context, val: Value) void
pub fn throwError(ctx: *Context, name: []const u8, message: []const u8) void
pub fn throwTypeError(ctx: *Context, message: []const u8) void
pub fn throwRangeError(ctx: *Context, message: []const u8) void
pub fn throwReferenceError(ctx: *Context, message: []const u8) void
pub fn throwSyntaxError(ctx: *Context, message: []const u8) void
ホスト側から JavaScript 例外を発生させます。いずれも pending exception スロットへ値を設定するのみで、Zig の制御フローは中断しません。詳細・使い分けは error を参照してください。
Event Loop/Timers¶
Context.setEventLoopHook / Context.clearEventLoopHook¶
pub fn setEventLoopHook(ctx: *Context, hook: EventLoopHook) void
pub fn clearEventLoopHook(ctx: *Context) void
setTimeout/setInterval/clearTimeout/clearInterval の実体をホストのイベントループへ委譲するフックを設定・解除します。フックの型は EventLoopHook を参照してください。フック未設定時、これらの組み込み関数は遅延を無視して即座にコールバックを実行します。
Context.fireTimer¶
EventLoopHook.set_timer で受け取った id のタイマーコールバックを実行します(ホストの実際のタイマー機構が発火したタイミングで呼び出す)。setInterval 由来のタイマー(is_repeat = true)は実行後も登録が残り、それ以外(setTimeout)は実行後に自動的に登録解除されます。実行後、内部でマイクロタスクのドレインと未処理 reject のチェックも行います。
Context.hasPendingTimers¶
clearTimeout/clearInterval されていない、発火待ちのタイマーが1つ以上あるかを返します。ホストのイベントループを「もう処理すべきものがないので終了してよいか」判定する際に使います。
Console/Handlers¶
Context.setConsoleHandler¶
console.log/info/warn/error/debug の出力先をホストコールバックに切り替えます。handler が設定されている間、各メソッドは引数を(String(arg) 相当で)結合したテキストと呼び出しレベルをコールバックへ渡し、標準出力へは出力しません。null を渡すと従来の標準出力への出力に戻ります。型は ConsoleHandler を参照してください。
Context.setUnhandledRejectionHandler¶
Promise が reject され、drainMicrotasks 完了時点でも reject ハンドラが一度も付いていない場合にホストへ通知するハンドラを設定します(HostPromiseRejectionTracker 相当)。null を渡すと通知を止めます。型は UnhandledRejectionHandler を参照してください。
決定的実行(Deterministic Execution)¶
Context.setDateNowMs¶
スクリプトから見える現在時刻(Date.now()、new Date() 等)を固定します。フレームクロックに同期した描画など、スクリプト可視の時刻を決定的にしたい場合に使います。null を渡すとシステムクロックに戻ります。
Context.setRandomSeed¶
Math.random() の背後にある決定的 PRNG を再シードします。エンジンは常に固定のデフォルトシードを使うため、再現性を保ったままセッション間で系列を変えたい場合にのみ必要です。
GC/Memory¶
Context.collectGarbage¶
GC サイクルを即座に1回実行します。GCMode.manual 時に明示的な回収を行うため、あるいは auto モードでもタイミングを制御したい場合に使います。
Context.requestInterrupt / Context.clearInterrupt¶
実行中のスクリプトを安全に中断させるための割り込みフラグを操作します。requestInterrupt を呼ぶと、実行中(または次に開始する)の eval/runScript/callFunction などが EvalError.RuntimeError を返して停止します(例外メッセージには "interrupted" を含む)。無限ループに陥ったスクリプトを別スレッド・シグナルハンドラなどから停止させる用途を想定しています。clearInterrupt はまだ消費されていない割り込み要求を取り消します。割り込み後も Context 自体は再利用可能です。
Context.setExecutionTimeLimitMs¶
以後の eval/evalModule/runScript/callFunction/fireTimer の各呼び出しに、壁時計ベースの実行時間バジェット(ミリ秒)を課します。バジェットは各エントリポイントの呼び出し時点からそれぞれ独立に計測され(ホスト関数から再入的に eval した場合、内側の呼び出しにも新しいバジェットが与えられ、外側の残り時間は内側の完了後に再開します)、超過すると実行中のスクリプトは Error("Execution time limit exceeded") の送出(EvalError.RuntimeError)で中断されます。中断後も Context は再利用可能です。null を渡すと制限を解除します。
- チェックは一定命令数(
WATCHDOG_INTERVAL= 4096 命令)ごとに行われるため、実際の超過検出はmsちょうどではなく若干の遅れを伴います。 requestInterrupt/clearInterruptとは独立で、互いに影響しません。- 時刻源は Linux の
clock_gettime(CLOCK_MONOTONIC)です。非 Linux ターゲットではクロックが常に 0 を返すため、設定した制限は事実上無効(恒久 no-op)になります。
Context.handleScope¶
短命な GC ルートスコープを開始します。戻り値の HandleScope.pin でオブジェクト値を一時的にルートし、HandleScope.close で巻き戻します。型の詳細は HandleScope を参照してください。
var scope = ctx.handleScope();
defer scope.close();
const obj = try ctx.eval("({value: 42})");
scope.pin(obj);
ctx.collectGarbage(); // obj は回収されない
Context.protect / Context.unprotect¶
pub fn protect(ctx: *Context, val: Value) PersistentHandle
pub fn unprotect(ctx: *Context, handle: PersistentHandle) void
HandleScope よりも長寿命な GC ルートを張ります。unprotect を呼ぶまで(あるいは ctx.deinit() まで)val は GC で回収されません。val が非オブジェクト値の場合、protect はダミーハンドルを返し、それに対する unprotect は安全に無視されます。型は PersistentHandle を参照してください。
Context.persistentGet¶
protect で作ったハンドルが現在指している値を返します。無効なハンドル(非オブジェクト値の protect が返すダミー、または unprotect 済みのスロット)では undefined を返します。主に C API(yjs_persistent_get)の下請けですが、Zig ホストからも利用できます。
Context.setGCMode¶
GC の起動方式を切り替えます(auto/manual)。型は GCMode を参照してください。
Context.suppressGC / Context.resumeGC¶
自動 GC を一時的に止め(suppressGC)、後で元のしきい値に戻します(resumeGC)。setGCMode(.manual) と異なり、resumeGC を呼ぶと suppressGC 呼び出し時点のしきい値設定に自動的に復帰する点が特徴で、一時的にアロケーションが多いクリティカルセクションを GC なしで走らせたい場合に向きます。ネストはサポートされません(2回目の suppressGC は1回目のしきい値を上書きします)。
Context.getGCStats¶
GC の統計情報のスナップショットを返します。型は GCStats を参照してください。
Context.setGCConfig¶
GC のしきい値・成長係数を設定します。config.initial_threshold は呼び出し直後の getGCStats().threshold に即座に反映されます。型は GCConfig を参照してください。
Context.getMemoryUsage¶
initWithMemoryLimit で作成した Context の現在の累計割り当てバイト数を返します。init(上限なし)で作成した Context では常に 0 を返します。
Context.getMemoryLimit¶
initWithMemoryLimit で設定した上限バイト数を返します。init で作成した Context では null。
Realms¶
Realm は、グローバル変数・組み込みプロトタイプの集合をひとまとめにした環境です。1つの Context 内で複数の Realm を切り替えることで、グローバル状態を分離した複数の実行環境を扱えます(詳細は Realm を参照)。
Context.createRealm¶
新しい Realm(組み込みオブジェクト一式を再構築した、独立したグローバル環境)を作成して返します。作成時点では現在の実行対象レルムには影響しません(setRealm で明示的に切り替えるまで有効化されません)。
Context.setRealm¶
以後の eval/getGlobal/setGlobal などが対象とするレルムを realm に切り替え、切り替え前のレルムを返します。元に戻したい場合は戻り値を保持しておき、再度 setRealm に渡してください。
なお、関数(クロージャ・組み込みとも)は作成されたレルムを記憶しており、レルムをまたいで呼び出された場合は実行中だけ自動的にその関数のレルムへ切り替わります(仕様の execution context の realm に相当)。別レルム由来の関数が投げるエラーはその関数のレルムの TypeError 等になり、prototype フォールバックもその関数のレルムの intrinsic が使われます。
Context.getRealm¶
現在アクティブなレルムを返します。
Context.destroyRealm¶
createRealm で作成したレルムを破棄します。現在アクティブなレルムを破棄してはいけません(setRealm で他のレルムに切り替えてから呼ぶこと)。また、Context.init 直後から存在するデフォルトレルム(ctx.deinit() が解放する)を destroyRealm に渡さないでください — 二重解放になります。
さらに、そのレルムで作成された関数オブジェクトは所属レルムへのポインタを保持しています。そのレルム由来の関数がまだ他のレルムから到達可能な状態で destroyRealm を呼ばないでください — 以後その関数を呼び出すと解放済みレルムを参照します。レルムを破棄するのは、そのレルム由来の値への参照をすべて手放した後にしてください。