feat: add render graph driven renderer architecture

Amp-Thread-ID: https://ampcode.com/threads/T-019f9d91-77c1-7206-a60f-ed6554ce92ab

Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-07-27 02:53:44 +00:00
co-authored by heaust
parent 8a8369706b
commit d4e8634f67
290 changed files with 48804 additions and 1995 deletions
@@ -0,0 +1,14 @@
export class AuthoringController {
#renderer; #getState; #revision=0; #nextRevision=1; #dirty=true; #applying=null; #listeners=new Set();
constructor({renderer,getState}) { this.#renderer=renderer; this.#getState=getState; }
get revision(){return this.#revision} get dirty(){return this.#dirty} get applying(){return !!this.#applying}
subscribe(fn){this.#listeners.add(fn);return()=>this.#listeners.delete(fn)}
markDirty(){this.#dirty=true;this.#emit()}
#emit(){for(const fn of this.#listeners)fn({revision:this.#revision,dirty:this.#dirty,applying:!!this.#applying})}
apply(adapt){
if(this.#applying)return this.#applying;
const revision=this.#nextRevision++; this.#dirty=false; this.#emit();
this.#applying=(async()=>{try{const snapshot=await this.#getState();const ir=adapt(snapshot,revision);const compiled=await this.#renderer.compileGraph(ir);await this.#renderer.switchCompiledGraph(compiled.compiledId);this.#revision=revision;return compiled} catch(e){this.#dirty=true;throw e} finally{this.#applying=null;this.#emit()}})();
return this.#applying;
}
}