Open4
nccc: Node.jsで絵が出るまで頑張る会

前にChez SchemeでやったのをNode.jsでやってみる。
問題になりそうなのは:
- ポインタとして
BigInt
を使いたいけどできるのか問題。過去には普通にJavaScript的な Number を使ってたけど、これはポインタの値域が53ビットを越えると危いので。また、 Duktape はそもそも BigInt をサポートしていないのでどうしようもない。。Hermes、XS、QuickJSはサポートしている。 - macOS上のNode.jsはスクリプトをメインスレッドで実行するのか問題。UIスレッドはメインスレッドでなければならない。

モジュールのlookupでいきなりつまづく
Node.jsは標準ベースの ECMA Script Module(ESM)と伝統的なCommonJSモジュールの両方をサポートしているがサポート範囲が絶妙に異なっている。
- ESMをESMなプログラム(= .mjs)からESMとしてロードする場合は拡張子を省略できない。
- ESMの
import
構文は ネイティブモジュールをロードできない。 ESMからネイティブモジュールをロードするには、CommonJSのrequire
をimportしてきて動的ロードとして使う。 - ESMをESMとしてロードする場合は、Node.js標準の
node_modules
検索パスは使われない。このパスは CommonJS 用。
いろいろ考えたけど、殆どのケースではESMで十分なので、Node.js固有のコードだけCommonJS形式にして、他をESM(= 相対パスでファイル名を直接指定)ということにした。
import { createRequire } from 'module';
// Node.js currently does not support loading native module
// using ES6 module syntax
const require = createRequire(import.meta.url);
const nccc = require("node-nccc");
const debug_prefix = require("nccc-debug-prefix");
export default {
nccc: nccc,
debug_prefix: debug_prefix
};
こういう感じで、 createRequire
を使うとCommonJSの require
を召喚できる。

モジュールローダーの作成
node-nccc
モジュールは dlfcn_open
と dlfcn_get
を提供しているので、それを使ってモジュールローダーを書く。(unloadは無い。動的ライブラリをアンロードする安全な方法は無いため。)
dlfcn_open: [path] => [res ptr]
dlfcn_close: [handle name] => [res ptr]
これらをJavaScript的なクロージャーにするにはネイティブモジュールに実装した make_nccc_call
を使う。
まぁこの辺は過去のコードのコピペで良いかな。

問題なく絵は出た
ちゃんとメインスレッドで動いているようだ。まだC-WebGLの関数を直接使っているが、これをまたWebGLにマップすれば前みたいにEmscriptenなプログラムも動かせるだろう。
const initr = yfrm_init();
const ctx_cwgl = yfrm_cwgl_ctx_create(1280, 720, 0, 1);
cwgl_viewport(ctx_cwgl, 0, 0, 1280, 720);
let cur = 0.0;
const evq = ncccutil.malloc(256 * 4);
const COLOR_BUFFER_BIT = 0x4000;
function fill(ctx){
yfrm_frame_begin0(ctx);
cwgl_clearColor(ctx, cur, cur, cur, cur);
cwgl_clear(ctx, COLOR_BUFFER_BIT);
yfrm_frame_end0(ctx);
}
function step(ctx){
yfrm_wait0(0);
const r = yfrm_query0(0, evq, 256 * 4);
console.log("EVENT:", r);
cur += 0.05;
if(cur > 1.0){
cur -= 1.0;
}
console.log(cur);
fill(ctx);
}
for(;;){
step(ctx_cwgl);
}