@vielzeug/ripple 2.2.1 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ripple.cjs +1 -1
- package/dist/ripple.cjs.map +1 -1
- package/dist/ripple.iife.js +1 -1
- package/dist/ripple.iife.js.map +1 -1
- package/dist/ripple.js +1 -1
- package/dist/ripple.js.map +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +2 -2
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
package/dist/ripple.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{},n=class extends e{},r=class extends e{},i=class extends e{},a=Symbol.for(`@vielzeug/ripple/reactive`),o=100,s=Symbol(`ripple.unset`),c=class{[a]=!0;dependents=new Set;name;runtime;constructor(e,t){this.runtime=e,this.name=t}subscribe(e){this.runtime.assertActive(),this.peek();let t={dependencies:new Set,onDependencyChanged:()=>this.runtime.enqueueListener(e)};return this.dependents.add(t),()=>this.dependents.delete(t)}notify(){for(let e of[...this.dependents])e.onDependencyChanged()}},l=class extends c{current;equals;constructor(e,t,n){super(e,n?.name),this.current=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.current}set value(e){if(this.runtime.assertActive(),this.equals(this.current,e))return;let t=this.current;this.current=e,this.runtime.emit({kind:`write`,name:this.name,next:e,previous:t}),this.runtime.propagate(()=>this.notify())}peek(){return this.current}update(e){this.value=e(this.current)}},u=class extends c{dependencies=new Set;computing=!1;disposed=!1;dirty=!0;current=s;derive;equals;constructor(e,t,n){super(e,n?.name),this.derive=t,this.equals=n?.equals??Object.is}get value(){return this.
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{},n=class extends e{},r=class extends e{},i=class extends e{},a=Symbol.for(`@vielzeug/ripple/reactive`),o=100,s=Symbol(`ripple.unset`),c=class{[a]=!0;dependents=new Set;name;runtime;constructor(e,t){this.runtime=e,this.name=t}subscribe(e){this.runtime.assertActive(),this.peek();let t={dependencies:new Set,onDependencyChanged:()=>this.runtime.enqueueListener(e)};return this.dependents.add(t),()=>this.dependents.delete(t)}notify(){for(let e of[...this.dependents])e.onDependencyChanged()}},l=class extends c{current;equals;constructor(e,t,n){super(e,n?.name),this.current=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.current}set value(e){if(this.runtime.assertActive(),this.equals(this.current,e))return;let t=this.current;this.current=e,this.runtime.emit({kind:`write`,name:this.name,next:e,previous:t}),this.runtime.propagate(()=>this.notify())}peek(){return this.current}update(e){this.value=e(this.current)}},u=class extends c{dependencies=new Set;computing=!1;disposed=!1;dirty=!0;current=s;derive;equals;constructor(e,t,n){super(e,n?.name),this.derive=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.refresh(),this.current}peek(){return this.refresh(),this.current}onDependencyChanged(){this.disposed||(this.dirty||=!0,this.dependents.size>0&&this.refresh()&&this.notify())}dispose(){this.disposed||(this.disposed=!0,this.runtime.clearDependencies(this),this.dependents.clear())}refresh(){if(!this.dirty||this.disposed)return!1;if(this.computing)throw new t(`computed cycle detected${this.name===void 0?``:` "${this.name}"`}`);this.computing=!0,this.runtime.emit({kind:`compute`,name:this.name});try{let e=this.runtime.collect(this,this.derive),t=this.current===s||!this.equals(this.current,e);return this.current=e,this.dirty=!1,t}finally{this.computing=!1}}},d=class{disposalController=new AbortController;owned=new Set;name;isDisposed=!1;runtime;constructor(e,t){this.runtime=e,this.name=t}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}run(e){if(this.isDisposed)throw new r(`Cannot run a disposed scope.`);return this.runtime.withScope(this,e)}dispose(){if(!this.isDisposed){this.isDisposed=!0;for(let e of[...this.owned].reverse())e.dispose();this.owned.clear(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.name,node:`scope`})}}[Symbol.dispose](){this.dispose()}},f=class{dependencies=new Set;disposalController=new AbortController;cleanup;isDisposed=!1;owner;scheduled=!1;callback;options;runtime;constructor(e,t,n){this.runtime=e,this.callback=t,this.options=n}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}onDependencyChanged(){if(!this.isDisposed){if(this.options?.scheduler===`microtask`){if(this.scheduled)return;this.scheduled=!0,queueMicrotask(()=>{this.scheduled=!1,this.isDisposed||this.runtime.enqueue(this)});return}this.runtime.enqueue(this)}}run(){if(this.isDisposed)return;this.owner?.dispose(),this.owner=void 0,this.runCleanup(),this.runtime.emit({kind:`effect`,name:this.options?.name});let e=new d(this.runtime);try{let t=this.runtime.withEffectScope(e,()=>this.runtime.collectEffect(this,this.callback));this.owner=e,this.cleanup=typeof t==`function`?t:void 0}catch(t){e.dispose(),this.runtime.report(t,{kind:`effect`,name:this.options?.name})}}dispose(){this.isDisposed||(this.isDisposed=!0,this.owner?.dispose(),this.owner=void 0,this.runtime.clearDependencies(this),this.runCleanup(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.options?.name,node:`effect`}))}[Symbol.dispose](){this.dispose()}runCleanup(){let e=this.cleanup;if(this.cleanup=void 0,e!==void 0)try{e()}catch(e){this.runtime.report(e,{kind:`cleanup`,name:this.options?.name})}}},p=class{activeEffectScope;activeObserver;activeScope;isDisposed=!1;flushDepth=0;flushing=!1;pending=new Set;listeners=new Set;rootScope;observer;onError;constructor(e){this.observer=e?.observer,this.onError=e?.onError??(e=>{queueMicrotask(()=>{throw e})}),this.rootScope=new d(this,`runtime`),this.activeScope=this.rootScope}get disposed(){return this.isDisposed}signal=(e,t)=>(this.assertActive(),new l(this,e,t));computed=(e,t)=>{this.assertActive();let n=new u(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n};effect=(e,t)=>{this.assertActive();let n=new f(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n.run(),n};createScope=e=>{this.assertActive();let t=new d(this,e);return this.activeScope.owned.add(t),t};batch=e=>(this.assertActive(),this.propagate(e));untrack=e=>(this.assertActive(),this.withObserver(void 0,e));dispose(){this.isDisposed||(this.isDisposed=!0,this.rootScope.dispose())}assertActive(){if(this.isDisposed)throw new n(`Cannot use a disposed Ripple runtime.`)}track(e){let t=this.activeObserver;t?.collecting!==void 0&&t.collecting.add(e)}clearDependencies(e){for(let t of e.dependencies)t.dependents.delete(e);e.dependencies.clear()}collect(e,t){return this.collectWith(e,t,e.dependencies.size===0)}collectEffect(e,t){return this.collectWith(e,t,!0)}withEffectScope(e,t){let n=this.activeEffectScope;this.activeEffectScope=e;try{return t()}finally{this.activeEffectScope=n}}withObserver(e,t){let n=this.activeObserver;this.activeObserver=e;try{return t()}finally{this.activeObserver=n}}withScope(e,t){let n=this.activeEffectScope,r=this.activeScope;this.activeEffectScope=void 0,this.activeScope=e;try{return t()}finally{this.activeEffectScope=n,this.activeScope=r}}enqueue(e){this.pending.add(e),this.flushDepth===0&&this.flush()}enqueueListener(e){this.listeners.add(e),this.flushDepth===0&&this.flush()}propagate(e){this.flushDepth++;try{return e()}finally{this.flushDepth--,this.flushDepth===0&&this.flush()}}emit(e){try{this.observer?.(e)}catch(t){this.report(t,{kind:`observer`,name:e.name})}}report(e,t){try{this.onError(e,t)}catch(e){queueMicrotask(()=>{throw e})}}collectWith(e,t,n){let r=this.activeObserver,i=new Set;e.collecting=i,this.activeObserver=e;try{let n=t();return this.commitDependencies(e,i),n}catch(t){throw n&&this.commitDependencies(e,i),t}finally{e.collecting=void 0,this.activeObserver=r}}commitDependencies(e,t){for(let n of e.dependencies)t.has(n)||n.dependents.delete(e);for(let n of t)e.dependencies.has(n)||n.dependents.add(e);e.dependencies.clear();for(let n of t)e.dependencies.add(n)}flush(){if(this.flushing)return;this.flushing=!0;let e=0;try{for(;this.pending.size>0||this.listeners.size>0;){if(++e>o)throw new i(`infinite reactive flush (>${o} iterations)`);let t=[...this.pending],n=[...this.listeners];this.pending.clear(),this.listeners.clear();for(let e of t)e.run();for(let e of n)try{e()}catch(e){this.report(e,{kind:`listener`})}}}finally{this.flushing=!1}}},m=e=>{if(typeof e!=`object`||!e||!(a in e))return!1;let t=e;return typeof t.peek==`function`&&typeof t.subscribe==`function`},h=e=>(t,n,r)=>{let i=e.signal({status:`pending`},{name:r?.name}),o=e.signal(0),s,c=!1,l=()=>{o.value,s?.abort();let e=i.peek(),r=e.status===`success`?e.value:`previous`in e?e.previous:void 0,a;try{a=t()}catch(e){i.value=r===void 0?{error:e,status:`error`}:{error:e,previous:r,status:`error`};return}let l=new AbortController;s=l,i.value=r===void 0?{status:`pending`}:{previous:r,status:`pending`};let u;try{u=Promise.resolve(n(a,{signal:l.signal}))}catch(e){u=Promise.reject(e)}u.then(e=>{!c&&!l.signal.aborted&&(i.value={status:`success`,value:e})},e=>{!c&&!l.signal.aborted&&(i.value=r===void 0?{error:e,status:`error`}:{error:e,previous:r,status:`error`})})},u=e.effect(()=>(l(),()=>s?.abort()),{name:r?.name});u.disposalSignal.addEventListener(`abort`,()=>{c=!0},{once:!0});let d={get disposalSignal(){return u.disposalSignal},dispose:()=>u.dispose(),get disposed(){return c},get name(){return i.name},peek:()=>i.peek(),reload:()=>{c||(o.value=o.peek()+1)},subscribe:e=>i.subscribe(e),[Symbol.dispose](){this.dispose()},get value(){return i.value}};return Object.defineProperty(d,a,{value:!0}),d},g=e=>(t,n,r)=>{let i=typeof t==`function`?t:()=>t.value,a=r?.equals??Object.is,o=!0,s,c=!1,l=e.effect(()=>{let e=i();if(o){o=!1,s=e,r?.immediate&&(n(e,void 0),r?.once&&(c=!0));return}if(a(s,e))return;let t=s;s=e,n(e,t),r?.once&&l.dispose()},{name:r?.name});return c&&l.dispose(),l},_=e=>{let t=new p(e),n=h(t);return{batch:t.batch,computed:t.computed,createScope:t.createScope,dispose:()=>t.dispose(),get disposed(){return t.disposed},effect:t.effect,resource:n,signal:t.signal,untrack:t.untrack,watch:g(t)}},v=_(),y=v.signal,b=v.computed,x=v.effect,S=v.batch,C=v.createScope,w=v.untrack,T=v.watch,E=v.resource;exports.RippleComputedCycleError=t,exports.RippleDisposedRuntimeError=n,exports.RippleDisposedScopeError=r,exports.RippleError=e,exports.RippleInfiniteLoopError=i,exports.batch=S,exports.computed=b,exports.createRipple=_,exports.createScope=C,exports.effect=x,exports.isReactive=m,exports.resource=E,exports.signal=y,exports.untrack=w,exports.watch=T;
|
|
2
2
|
//# sourceMappingURL=ripple.cjs.map
|
package/dist/ripple.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ripple.cjs","names":[],"sources":["../src/errors.ts","../src/runtime.ts","../src/_async.ts","../src/_watch.ts","../src/_default.ts","../src/index.ts"],"sourcesContent":["export class RippleError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class RippleComputedCycleError extends RippleError {}\nexport class RippleDisposedRuntimeError extends RippleError {}\nexport class RippleDisposedScopeError extends RippleError {}\nexport class RippleInfiniteLoopError extends RippleError {}\n","import {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleInfiniteLoopError,\n} from './errors';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n ReactiveErrorContext,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nexport const REACTIVE = Symbol.for('@vielzeug/ripple/reactive');\nconst MAX_FLUSH_ITERATIONS = 100;\nconst UNSET = Symbol('ripple.unset');\n\ntype Dependency = ReactiveNode<unknown>;\n\ntype ObserverNode = {\n collecting?: Set<Dependency>;\n readonly dependencies: Set<Dependency>;\n onDependencyChanged(): void;\n};\n\ntype Owned = {\n dispose(): void;\n};\n\nabstract class ReactiveNode<T> {\n readonly [REACTIVE] = true;\n readonly dependents = new Set<ObserverNode>();\n readonly name: string | undefined;\n protected readonly runtime: ReactiveRuntime;\n\n protected constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n abstract peek(): T;\n abstract get value(): T;\n\n subscribe(listener: () => void): Unsubscribe {\n this.runtime.assertActive();\n this.peek();\n\n const observer: ObserverNode = {\n dependencies: new Set(),\n onDependencyChanged: () => this.runtime.enqueueListener(listener),\n };\n\n this.dependents.add(observer);\n\n return () => this.dependents.delete(observer);\n }\n\n protected notify(): void {\n for (const dependent of [...this.dependents]) dependent.onDependencyChanged();\n }\n}\n\nclass SignalNode<T> extends ReactiveNode<T> implements Signal<T> {\n private current: T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, initial: T, options?: SignalOptions<T>) {\n super(runtime, options?.name);\n this.current = initial;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.runtime.track(this);\n\n return this.current;\n }\n\n set value(next: T) {\n this.runtime.assertActive();\n\n if (this.equals(this.current, next)) return;\n\n const previous = this.current;\n\n this.current = next;\n this.runtime.emit({ kind: 'write', name: this.name, next, previous });\n this.runtime.propagate(() => this.notify());\n }\n\n peek(): T {\n return this.current;\n }\n\n update(updater: (prev: T) => T): void {\n this.value = updater(this.current);\n }\n}\n\nclass ComputedNode<T> extends ReactiveNode<T> implements ObserverNode, Owned {\n readonly dependencies = new Set<Dependency>();\n private computing = false;\n private disposed = false;\n private dirty = true;\n private current: T | typeof UNSET = UNSET;\n private readonly derive: () => T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, derive: () => T, options?: ComputedOptions<T>) {\n super(runtime, options?.name);\n this.derive = derive;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.refresh();\n this.runtime.track(this);\n\n return this.current as T;\n }\n\n peek(): T {\n this.refresh();\n\n return this.current as T;\n }\n\n onDependencyChanged(): void {\n if (this.disposed) return;\n\n if (!this.dirty) this.dirty = true;\n\n if (this.dependents.size > 0 && this.refresh()) this.notify();\n }\n\n dispose(): void {\n if (this.disposed) return;\n\n this.disposed = true;\n this.runtime.clearDependencies(this);\n this.dependents.clear();\n }\n\n private refresh(): boolean {\n if (!this.dirty || this.disposed) return false;\n\n if (this.computing) {\n const label = this.name === undefined ? '' : ` \"${this.name}\"`;\n\n throw new RippleComputedCycleError(`computed cycle detected${label}`);\n }\n\n this.computing = true;\n this.runtime.emit({ kind: 'compute', name: this.name });\n\n try {\n const next = this.runtime.collect(this, this.derive);\n const changed = this.current === UNSET || !this.equals(this.current as T, next);\n\n this.current = next;\n this.dirty = false;\n\n return changed;\n } finally {\n this.computing = false;\n }\n }\n}\n\nclass ScopeNode implements Scope {\n readonly disposalController = new AbortController();\n readonly owned = new Set<Owned>();\n readonly name: string | undefined;\n private isDisposed = false;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n run<T>(fn: () => T): T {\n if (this.isDisposed) throw new RippleDisposedScopeError('Cannot run a disposed scope.');\n\n return this.runtime.withScope(this, fn);\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n for (const owned of [...this.owned].reverse()) owned.dispose();\n this.owned.clear();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.name, node: 'scope' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nclass EffectNode implements ObserverNode, EffectHandle {\n readonly dependencies = new Set<Dependency>();\n readonly disposalController = new AbortController();\n private cleanup: Cleanup | undefined;\n private isDisposed = false;\n private owner: ScopeNode | undefined;\n private scheduled = false;\n private readonly callback: () => Cleanup | undefined;\n private readonly options: EffectOptions | undefined;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, callback: () => Cleanup | undefined, options?: EffectOptions) {\n this.runtime = runtime;\n this.callback = callback;\n this.options = options;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n onDependencyChanged(): void {\n if (this.isDisposed) return;\n\n if (this.options?.scheduler === 'microtask') {\n if (this.scheduled) return;\n\n this.scheduled = true;\n queueMicrotask(() => {\n this.scheduled = false;\n\n if (!this.isDisposed) this.runtime.enqueue(this);\n });\n\n return;\n }\n\n this.runtime.enqueue(this);\n }\n\n run(): void {\n if (this.isDisposed) return;\n\n this.owner?.dispose();\n this.owner = undefined;\n this.runCleanup();\n this.runtime.emit({ kind: 'effect', name: this.options?.name });\n\n const owner = new ScopeNode(this.runtime);\n\n try {\n const cleanup = this.runtime.withEffectScope(owner, () => this.runtime.collectEffect(this, this.callback));\n\n this.owner = owner;\n this.cleanup = typeof cleanup === 'function' ? cleanup : undefined;\n } catch (error) {\n owner.dispose();\n this.runtime.report(error, { kind: 'effect', name: this.options?.name });\n }\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.owner?.dispose();\n this.owner = undefined;\n this.runtime.clearDependencies(this);\n this.runCleanup();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.options?.name, node: 'effect' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n private runCleanup(): void {\n const cleanup = this.cleanup;\n\n this.cleanup = undefined;\n\n if (cleanup === undefined) return;\n\n try {\n cleanup();\n } catch (error) {\n this.runtime.report(error, { kind: 'cleanup', name: this.options?.name });\n }\n }\n}\n\n/**\n * A runtime owns reactive graph state and lifetime. Separate instances isolate\n * applications and SSR requests without process-wide mutable hooks.\n */\nexport class ReactiveRuntime {\n private activeEffectScope: ScopeNode | undefined;\n private activeObserver: ObserverNode | undefined;\n private activeScope: ScopeNode;\n private isDisposed = false;\n private flushDepth = 0;\n private flushing = false;\n private readonly pending = new Set<EffectNode>();\n private readonly listeners = new Set<() => void>();\n private readonly rootScope: ScopeNode;\n private readonly observer: ReactiveObserver | undefined;\n private readonly onError: (error: unknown, context: ReactiveErrorContext) => void;\n\n constructor(options?: RippleOptions) {\n this.observer = options?.observer;\n this.onError =\n options?.onError ??\n ((error) => {\n queueMicrotask(() => {\n throw error;\n });\n });\n this.rootScope = new ScopeNode(this, 'runtime');\n this.activeScope = this.rootScope;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n readonly signal = <T>(initial: T, options?: SignalOptions<T>): Signal<T> => {\n this.assertActive();\n\n return new SignalNode(this, initial, options);\n };\n\n readonly computed = <T>(derive: () => T, options?: ComputedOptions<T>): Readable<T> => {\n this.assertActive();\n\n const node = new ComputedNode(this, derive, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n\n return node;\n };\n\n readonly effect = (callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle => {\n this.assertActive();\n\n const node = new EffectNode(this, callback, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n node.run();\n\n return node;\n };\n\n readonly createScope = (name?: string): Scope => {\n this.assertActive();\n\n const scope = new ScopeNode(this, name);\n\n // Scopes model explicit, caller-owned lifetimes. Unlike effects/computeds created during an\n // effect run, they deliberately attach to the enclosing scope rather than the per-run owner:\n // keyed DOM directives retain item scopes across reconciliation runs and dispose them only\n // when the item itself leaves the collection.\n this.activeScope.owned.add(scope);\n\n return scope;\n };\n\n readonly batch = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.propagate(fn);\n };\n\n readonly untrack = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.withObserver(undefined, fn);\n };\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.rootScope.dispose();\n }\n\n /** Internal node guard: disposed runtimes allow inert reads but reject graph work and mutation. */\n assertActive(): void {\n if (this.isDisposed) throw new RippleDisposedRuntimeError('Cannot use a disposed Ripple runtime.');\n }\n\n track(node: Dependency): void {\n const observer = this.activeObserver;\n\n if (observer?.collecting === undefined) return;\n\n observer.collecting.add(node);\n }\n\n clearDependencies(observer: ObserverNode): void {\n for (const dependency of observer.dependencies) dependency.dependents.delete(observer);\n observer.dependencies.clear();\n }\n\n collect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, false);\n }\n\n collectEffect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, true);\n }\n\n withEffectScope<T>(scope: ScopeNode, fn: () => T): T {\n const previous = this.activeEffectScope;\n\n this.activeEffectScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previous;\n }\n }\n\n withObserver<T>(observer: ObserverNode | undefined, fn: () => T): T {\n const previous = this.activeObserver;\n\n this.activeObserver = observer;\n\n try {\n return fn();\n } finally {\n this.activeObserver = previous;\n }\n }\n\n withScope<T>(scope: ScopeNode, fn: () => T): T {\n const previousEffectScope = this.activeEffectScope;\n const previousScope = this.activeScope;\n\n this.activeEffectScope = undefined;\n this.activeScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previousEffectScope;\n this.activeScope = previousScope;\n }\n }\n\n enqueue(effect: EffectNode): void {\n this.pending.add(effect);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n enqueueListener(listener: () => void): void {\n this.listeners.add(listener);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n propagate<T>(fn: () => T): T {\n this.flushDepth++;\n\n try {\n return fn();\n } finally {\n this.flushDepth--;\n\n if (this.flushDepth === 0) this.flush();\n }\n }\n\n emit(event: Parameters<ReactiveObserver>[0]): void {\n try {\n this.observer?.(event);\n } catch (error) {\n this.report(error, { kind: 'observer', name: event.name });\n }\n }\n\n report(error: unknown, context: ReactiveErrorContext): void {\n try {\n this.onError(error, context);\n } catch (reporterError) {\n queueMicrotask(() => {\n throw reporterError;\n });\n }\n }\n\n private collectWith<T>(observer: ObserverNode, fn: () => T, commitOnError: boolean): T {\n const previousObserver = this.activeObserver;\n const dependencies = new Set<Dependency>();\n\n observer.collecting = dependencies;\n this.activeObserver = observer;\n\n try {\n const result = fn();\n\n this.commitDependencies(observer, dependencies);\n\n return result;\n } catch (error) {\n if (commitOnError) this.commitDependencies(observer, dependencies);\n\n throw error;\n } finally {\n observer.collecting = undefined;\n this.activeObserver = previousObserver;\n }\n }\n\n private commitDependencies(observer: ObserverNode, next: Set<Dependency>): void {\n for (const dependency of observer.dependencies) {\n if (!next.has(dependency)) dependency.dependents.delete(observer);\n }\n\n for (const dependency of next) {\n if (!observer.dependencies.has(dependency)) dependency.dependents.add(observer);\n }\n\n observer.dependencies.clear();\n for (const dependency of next) observer.dependencies.add(dependency);\n }\n\n private flush(): void {\n if (this.flushing) return;\n\n this.flushing = true;\n\n let iterations = 0;\n\n try {\n while (this.pending.size > 0 || this.listeners.size > 0) {\n if (++iterations > MAX_FLUSH_ITERATIONS) {\n throw new RippleInfiniteLoopError(`infinite reactive flush (>${MAX_FLUSH_ITERATIONS} iterations)`);\n }\n\n const effects = [...this.pending];\n const listeners = [...this.listeners];\n\n this.pending.clear();\n this.listeners.clear();\n\n for (const effect of effects) effect.run();\n\n for (const listener of listeners) {\n try {\n listener();\n } catch (error) {\n this.report(error, { kind: 'listener' });\n }\n }\n }\n } finally {\n this.flushing = false;\n }\n }\n}\n\nexport const isReactive = <T>(value: T | Readable<T>): value is Readable<T> => {\n if (typeof value !== 'object' || value === null || !(REACTIVE in value)) return false;\n\n const candidate = value as { peek?: unknown; subscribe?: unknown };\n\n return typeof candidate.peek === 'function' && typeof candidate.subscribe === 'function';\n};\n","import { REACTIVE } from './runtime';\nimport type { Disposable, EffectHandle, Readable, Signal } from './types';\n\nexport type AsyncState<T> =\n | { readonly previous?: T; readonly status: 'pending' }\n | { readonly status: 'success'; readonly value: T }\n | { readonly error: unknown; readonly previous?: T; readonly status: 'error' };\n\nexport interface Resource<T> extends Readable<AsyncState<T>>, Disposable {\n reload(): void;\n}\n\nexport type ResourceOptions = {\n name?: string;\n};\n\ntype AsyncRuntime = {\n effect(callback: () => undefined | (() => void), options?: { name?: string }): EffectHandle;\n signal<T>(initial: T, options?: { name?: string }): Signal<T>;\n};\n\n/** Resource only depends on primitive runtime methods; graph binding stays private. */\nexport const createResource =\n (runtime: AsyncRuntime) =>\n <Source, Value>(\n source: () => Source,\n loader: (source: Source, context: { readonly signal: AbortSignal }) => Promise<Value>,\n options?: ResourceOptions,\n ): Resource<Value> => {\n const state = runtime.signal<AsyncState<Value>>({ status: 'pending' }, { name: options?.name });\n const reloadEpoch = runtime.signal(0);\n let active: AbortController | undefined;\n let disposed = false;\n\n const run = (): void => {\n void reloadEpoch.value;\n active?.abort();\n\n const current = state.peek();\n const previous =\n current.status === 'success' ? current.value : 'previous' in current ? current.previous : undefined;\n let input: Source;\n\n try {\n input = source();\n } catch (error) {\n state.value = previous === undefined ? { error, status: 'error' } : { error, previous, status: 'error' };\n\n return;\n }\n\n const next = new AbortController();\n\n active = next;\n state.value = previous === undefined ? { status: 'pending' } : { previous, status: 'pending' };\n\n let request: Promise<Value>;\n\n try {\n request = Promise.resolve(loader(input, { signal: next.signal }));\n } catch (error) {\n request = Promise.reject(error);\n }\n\n void request.then(\n (value) => {\n if (!disposed && !next.signal.aborted) state.value = { status: 'success', value };\n },\n (error: unknown) => {\n if (!disposed && !next.signal.aborted) {\n state.value = previous === undefined ? { error, status: 'error' } : { error, previous, status: 'error' };\n }\n },\n );\n };\n\n const stop = runtime.effect(\n () => {\n run();\n\n return () => active?.abort();\n },\n { name: options?.name },\n );\n\n stop.disposalSignal.addEventListener(\n 'abort',\n () => {\n disposed = true;\n },\n { once: true },\n );\n\n const resource: Resource<Value> = {\n get disposalSignal() {\n return stop.disposalSignal;\n },\n dispose: () => stop.dispose(),\n get disposed() {\n return disposed;\n },\n get name() {\n return state.name;\n },\n peek: () => state.peek(),\n reload: () => {\n if (disposed) return;\n\n reloadEpoch.value = reloadEpoch.peek() + 1;\n },\n subscribe: (listener) => state.subscribe(listener),\n [Symbol.dispose]() {\n this.dispose();\n },\n get value() {\n return state.value;\n },\n };\n\n Object.defineProperty(resource, REACTIVE, { value: true });\n\n return resource;\n };\n","import type { EffectHandle, Equality, Readable } from './types';\n\nexport type WatchOptions<T> = {\n equals?: Equality<T>;\n immediate?: boolean;\n name?: string;\n once?: boolean;\n};\n\ntype WatchRuntime = {\n effect(callback: () => undefined | (() => void), options?: { name?: string }): EffectHandle;\n};\n\nexport const createWatch =\n (runtime: WatchRuntime) =>\n <T>(\n source: Readable<T> | (() => T),\n callback: (value: T, previous: T | undefined) => void,\n options?: WatchOptions<T>,\n ): EffectHandle => {\n const read = typeof source === 'function' ? source : () => source.value;\n const equals = options?.equals ?? Object.is;\n let initial = true;\n let previous: T | undefined;\n // `handle` is in the temporal dead zone during the effect's initial synchronous run —\n // `runtime.effect()` calls `node.run()` before returning. Defer disposal until after\n // the constructor returns so `handle.dispose()` is reachable from inside the callback.\n let disposeAfterInit = false;\n\n const handle = runtime.effect(\n () => {\n const value = read();\n\n if (initial) {\n initial = false;\n previous = value;\n\n if (options?.immediate) {\n callback(value, undefined);\n if (options?.once) disposeAfterInit = true;\n }\n\n return;\n }\n\n if (equals(previous as T, value)) return;\n\n const oldValue = previous;\n\n previous = value;\n callback(value, oldValue);\n\n if (options?.once) handle.dispose();\n },\n { name: options?.name },\n );\n\n if (disposeAfterInit) handle.dispose();\n\n return handle;\n };\n","import { createResource, type Resource, type ResourceOptions } from './_async';\nimport { createWatch, type WatchOptions } from './_watch';\nimport { ReactiveRuntime } from './runtime';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n} from './types';\n\nexport interface Ripple {\n batch<T>(fn: () => T): T;\n computed<T>(derive: () => T, options?: ComputedOptions<T>): Readable<T>;\n createScope(name?: string): Scope;\n dispose(): void;\n readonly disposed: boolean;\n effect(callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle;\n resource<Source, Value>(\n source: () => Source,\n loader: (source: Source, context: { readonly signal: AbortSignal }) => Promise<Value>,\n options?: ResourceOptions,\n ): Resource<Value>;\n signal<T>(initial: T, options?: SignalOptions<T>): Signal<T>;\n untrack<T>(fn: () => T): T;\n watch<T>(\n source: Readable<T> | (() => T),\n callback: (value: T, previous: T | undefined) => void,\n options?: WatchOptions<T>,\n ): EffectHandle;\n}\n\n/** Creates one complete reactive graph. All factories on the object share its runtime. */\nexport const createRipple = (options?: RippleOptions): Ripple => {\n const runtime = new ReactiveRuntime(options);\n const resource = createResource(runtime);\n\n return {\n batch: runtime.batch,\n computed: runtime.computed,\n createScope: runtime.createScope,\n dispose: () => runtime.dispose(),\n get disposed() {\n return runtime.disposed;\n },\n effect: runtime.effect,\n resource,\n signal: runtime.signal,\n untrack: runtime.untrack,\n watch: createWatch(runtime),\n };\n};\n\n/**\n * The shared default reactive graph. Private — `signal`, `computed`, `effect`, `batch`,\n * `createScope`, `untrack`, `watch`, and `resource` are re-exported from the package root\n * as bound methods on this single graph instance.\n */\nexport const defaultRipple = createRipple();\n","export type { AsyncState, Resource, ResourceOptions } from './_async';\nexport { createRipple, type Ripple } from './_default';\nexport type { WatchOptions } from './_watch';\nexport {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleError,\n RippleInfiniteLoopError,\n} from './errors';\nexport { isReactive } from './runtime';\nexport type {\n Cleanup,\n ComputedOptions,\n Disposable,\n EffectHandle,\n EffectOptions,\n Equality,\n ReactiveErrorContext,\n ReactiveEvent,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nimport { defaultRipple } from './_default';\n\nexport const signal = defaultRipple.signal;\nexport const computed = defaultRipple.computed;\nexport const effect = defaultRipple.effect;\nexport const batch = defaultRipple.batch;\nexport const createScope = defaultRipple.createScope;\nexport const untrack = defaultRipple.untrack;\nexport const watch = defaultRipple.watch;\nexport const resource = defaultRipple.resource;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ripple.cjs","names":[],"sources":["../src/errors.ts","../src/runtime.ts","../src/_async.ts","../src/_watch.ts","../src/_default.ts","../src/index.ts"],"sourcesContent":["export class RippleError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class RippleComputedCycleError extends RippleError {}\nexport class RippleDisposedRuntimeError extends RippleError {}\nexport class RippleDisposedScopeError extends RippleError {}\nexport class RippleInfiniteLoopError extends RippleError {}\n","import {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleInfiniteLoopError,\n} from './errors';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n ReactiveErrorContext,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nexport const REACTIVE = Symbol.for('@vielzeug/ripple/reactive');\nconst MAX_FLUSH_ITERATIONS = 100;\nconst UNSET = Symbol('ripple.unset');\n\ntype Dependency = ReactiveNode<unknown>;\n\ntype ObserverNode = {\n collecting?: Set<Dependency>;\n readonly dependencies: Set<Dependency>;\n onDependencyChanged(): void;\n};\n\ntype Owned = {\n dispose(): void;\n};\n\nabstract class ReactiveNode<T> {\n readonly [REACTIVE] = true;\n readonly dependents = new Set<ObserverNode>();\n readonly name: string | undefined;\n protected readonly runtime: ReactiveRuntime;\n\n protected constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n abstract peek(): T;\n abstract get value(): T;\n\n subscribe(listener: () => void): Unsubscribe {\n this.runtime.assertActive();\n this.peek();\n\n const observer: ObserverNode = {\n dependencies: new Set(),\n onDependencyChanged: () => this.runtime.enqueueListener(listener),\n };\n\n this.dependents.add(observer);\n\n return () => this.dependents.delete(observer);\n }\n\n protected notify(): void {\n for (const dependent of [...this.dependents]) dependent.onDependencyChanged();\n }\n}\n\nclass SignalNode<T> extends ReactiveNode<T> implements Signal<T> {\n private current: T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, initial: T, options?: SignalOptions<T>) {\n super(runtime, options?.name);\n this.current = initial;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.runtime.track(this);\n\n return this.current;\n }\n\n set value(next: T) {\n this.runtime.assertActive();\n\n if (this.equals(this.current, next)) return;\n\n const previous = this.current;\n\n this.current = next;\n this.runtime.emit({ kind: 'write', name: this.name, next, previous });\n this.runtime.propagate(() => this.notify());\n }\n\n peek(): T {\n return this.current;\n }\n\n update(updater: (prev: T) => T): void {\n this.value = updater(this.current);\n }\n}\n\nclass ComputedNode<T> extends ReactiveNode<T> implements ObserverNode, Owned {\n readonly dependencies = new Set<Dependency>();\n private computing = false;\n private disposed = false;\n private dirty = true;\n private current: T | typeof UNSET = UNSET;\n private readonly derive: () => T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, derive: () => T, options?: ComputedOptions<T>) {\n super(runtime, options?.name);\n this.derive = derive;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n // Track before refresh: if refresh throws, the consumer still depends on\n // this computed and must be notified when a dependency change might let it\n // succeed. Without this, a first-run failure permanently severs the\n // consumer from the computed.\n this.runtime.track(this);\n this.refresh();\n\n return this.current as T;\n }\n\n peek(): T {\n this.refresh();\n\n return this.current as T;\n }\n\n onDependencyChanged(): void {\n if (this.disposed) return;\n\n if (!this.dirty) this.dirty = true;\n\n if (this.dependents.size > 0 && this.refresh()) this.notify();\n }\n\n dispose(): void {\n if (this.disposed) return;\n\n this.disposed = true;\n this.runtime.clearDependencies(this);\n this.dependents.clear();\n }\n\n private refresh(): boolean {\n if (!this.dirty || this.disposed) return false;\n\n if (this.computing) {\n const label = this.name === undefined ? '' : ` \"${this.name}\"`;\n\n throw new RippleComputedCycleError(`computed cycle detected${label}`);\n }\n\n this.computing = true;\n this.runtime.emit({ kind: 'compute', name: this.name });\n\n try {\n const next = this.runtime.collect(this, this.derive);\n const changed = this.current === UNSET || !this.equals(this.current as T, next);\n\n this.current = next;\n this.dirty = false;\n\n return changed;\n } finally {\n this.computing = false;\n }\n }\n}\n\nclass ScopeNode implements Scope {\n readonly disposalController = new AbortController();\n readonly owned = new Set<Owned>();\n readonly name: string | undefined;\n private isDisposed = false;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n run<T>(fn: () => T): T {\n if (this.isDisposed) throw new RippleDisposedScopeError('Cannot run a disposed scope.');\n\n return this.runtime.withScope(this, fn);\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n for (const owned of [...this.owned].reverse()) owned.dispose();\n this.owned.clear();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.name, node: 'scope' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nclass EffectNode implements ObserverNode, EffectHandle {\n readonly dependencies = new Set<Dependency>();\n readonly disposalController = new AbortController();\n private cleanup: Cleanup | undefined;\n private isDisposed = false;\n private owner: ScopeNode | undefined;\n private scheduled = false;\n private readonly callback: () => Cleanup | undefined;\n private readonly options: EffectOptions | undefined;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, callback: () => Cleanup | undefined, options?: EffectOptions) {\n this.runtime = runtime;\n this.callback = callback;\n this.options = options;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n onDependencyChanged(): void {\n if (this.isDisposed) return;\n\n if (this.options?.scheduler === 'microtask') {\n if (this.scheduled) return;\n\n this.scheduled = true;\n queueMicrotask(() => {\n this.scheduled = false;\n\n if (!this.isDisposed) this.runtime.enqueue(this);\n });\n\n return;\n }\n\n this.runtime.enqueue(this);\n }\n\n run(): void {\n if (this.isDisposed) return;\n\n this.owner?.dispose();\n this.owner = undefined;\n this.runCleanup();\n this.runtime.emit({ kind: 'effect', name: this.options?.name });\n\n const owner = new ScopeNode(this.runtime);\n\n try {\n const cleanup = this.runtime.withEffectScope(owner, () => this.runtime.collectEffect(this, this.callback));\n\n this.owner = owner;\n this.cleanup = typeof cleanup === 'function' ? cleanup : undefined;\n } catch (error) {\n owner.dispose();\n this.runtime.report(error, { kind: 'effect', name: this.options?.name });\n }\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.owner?.dispose();\n this.owner = undefined;\n this.runtime.clearDependencies(this);\n this.runCleanup();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.options?.name, node: 'effect' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n private runCleanup(): void {\n const cleanup = this.cleanup;\n\n this.cleanup = undefined;\n\n if (cleanup === undefined) return;\n\n try {\n cleanup();\n } catch (error) {\n this.runtime.report(error, { kind: 'cleanup', name: this.options?.name });\n }\n }\n}\n\n/**\n * A runtime owns reactive graph state and lifetime. Separate instances isolate\n * applications and SSR requests without process-wide mutable hooks.\n */\nexport class ReactiveRuntime {\n private activeEffectScope: ScopeNode | undefined;\n private activeObserver: ObserverNode | undefined;\n private activeScope: ScopeNode;\n private isDisposed = false;\n private flushDepth = 0;\n private flushing = false;\n private readonly pending = new Set<EffectNode>();\n private readonly listeners = new Set<() => void>();\n private readonly rootScope: ScopeNode;\n private readonly observer: ReactiveObserver | undefined;\n private readonly onError: (error: unknown, context: ReactiveErrorContext) => void;\n\n constructor(options?: RippleOptions) {\n this.observer = options?.observer;\n this.onError =\n options?.onError ??\n ((error) => {\n queueMicrotask(() => {\n throw error;\n });\n });\n this.rootScope = new ScopeNode(this, 'runtime');\n this.activeScope = this.rootScope;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n readonly signal = <T>(initial: T, options?: SignalOptions<T>): Signal<T> => {\n this.assertActive();\n\n return new SignalNode(this, initial, options);\n };\n\n readonly computed = <T>(derive: () => T, options?: ComputedOptions<T>): Readable<T> => {\n this.assertActive();\n\n const node = new ComputedNode(this, derive, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n\n return node;\n };\n\n readonly effect = (callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle => {\n this.assertActive();\n\n const node = new EffectNode(this, callback, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n node.run();\n\n return node;\n };\n\n readonly createScope = (name?: string): Scope => {\n this.assertActive();\n\n const scope = new ScopeNode(this, name);\n\n // Scopes model explicit, caller-owned lifetimes. Unlike effects/computeds created during an\n // effect run, they deliberately attach to the enclosing scope rather than the per-run owner:\n // keyed DOM directives retain item scopes across reconciliation runs and dispose them only\n // when the item itself leaves the collection.\n this.activeScope.owned.add(scope);\n\n return scope;\n };\n\n readonly batch = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.propagate(fn);\n };\n\n readonly untrack = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.withObserver(undefined, fn);\n };\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.rootScope.dispose();\n }\n\n /** Internal node guard: disposed runtimes allow inert reads but reject graph work and mutation. */\n assertActive(): void {\n if (this.isDisposed) throw new RippleDisposedRuntimeError('Cannot use a disposed Ripple runtime.');\n }\n\n track(node: Dependency): void {\n const observer = this.activeObserver;\n\n if (observer?.collecting === undefined) return;\n\n observer.collecting.add(node);\n }\n\n clearDependencies(observer: ObserverNode): void {\n for (const dependency of observer.dependencies) dependency.dependents.delete(observer);\n observer.dependencies.clear();\n }\n\n collect<T>(observer: ObserverNode, fn: () => T): T {\n // On first run (no prior dependencies), commit partial dependencies even if\n // derive throws — otherwise the computed would have zero dependencies and never\n // be notified when its source changes, permanently stuck until a manual read.\n // On subsequent runs, keep previous dependencies (tested behavior).\n return this.collectWith(observer, fn, observer.dependencies.size === 0);\n }\n\n collectEffect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, true);\n }\n\n withEffectScope<T>(scope: ScopeNode, fn: () => T): T {\n const previous = this.activeEffectScope;\n\n this.activeEffectScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previous;\n }\n }\n\n withObserver<T>(observer: ObserverNode | undefined, fn: () => T): T {\n const previous = this.activeObserver;\n\n this.activeObserver = observer;\n\n try {\n return fn();\n } finally {\n this.activeObserver = previous;\n }\n }\n\n withScope<T>(scope: ScopeNode, fn: () => T): T {\n const previousEffectScope = this.activeEffectScope;\n const previousScope = this.activeScope;\n\n this.activeEffectScope = undefined;\n this.activeScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previousEffectScope;\n this.activeScope = previousScope;\n }\n }\n\n enqueue(effect: EffectNode): void {\n this.pending.add(effect);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n enqueueListener(listener: () => void): void {\n this.listeners.add(listener);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n propagate<T>(fn: () => T): T {\n this.flushDepth++;\n\n try {\n return fn();\n } finally {\n this.flushDepth--;\n\n if (this.flushDepth === 0) this.flush();\n }\n }\n\n emit(event: Parameters<ReactiveObserver>[0]): void {\n try {\n this.observer?.(event);\n } catch (error) {\n this.report(error, { kind: 'observer', name: event.name });\n }\n }\n\n report(error: unknown, context: ReactiveErrorContext): void {\n try {\n this.onError(error, context);\n } catch (reporterError) {\n queueMicrotask(() => {\n throw reporterError;\n });\n }\n }\n\n private collectWith<T>(observer: ObserverNode, fn: () => T, commitOnError: boolean): T {\n const previousObserver = this.activeObserver;\n const dependencies = new Set<Dependency>();\n\n observer.collecting = dependencies;\n this.activeObserver = observer;\n\n try {\n const result = fn();\n\n this.commitDependencies(observer, dependencies);\n\n return result;\n } catch (error) {\n if (commitOnError) this.commitDependencies(observer, dependencies);\n\n throw error;\n } finally {\n observer.collecting = undefined;\n this.activeObserver = previousObserver;\n }\n }\n\n private commitDependencies(observer: ObserverNode, next: Set<Dependency>): void {\n for (const dependency of observer.dependencies) {\n if (!next.has(dependency)) dependency.dependents.delete(observer);\n }\n\n for (const dependency of next) {\n if (!observer.dependencies.has(dependency)) dependency.dependents.add(observer);\n }\n\n observer.dependencies.clear();\n for (const dependency of next) observer.dependencies.add(dependency);\n }\n\n private flush(): void {\n if (this.flushing) return;\n\n this.flushing = true;\n\n let iterations = 0;\n\n try {\n while (this.pending.size > 0 || this.listeners.size > 0) {\n if (++iterations > MAX_FLUSH_ITERATIONS) {\n throw new RippleInfiniteLoopError(`infinite reactive flush (>${MAX_FLUSH_ITERATIONS} iterations)`);\n }\n\n const effects = [...this.pending];\n const listeners = [...this.listeners];\n\n this.pending.clear();\n this.listeners.clear();\n\n for (const effect of effects) effect.run();\n\n for (const listener of listeners) {\n try {\n listener();\n } catch (error) {\n this.report(error, { kind: 'listener' });\n }\n }\n }\n } finally {\n this.flushing = false;\n }\n }\n}\n\nexport const isReactive = <T>(value: T | Readable<T>): value is Readable<T> => {\n if (typeof value !== 'object' || value === null || !(REACTIVE in value)) return false;\n\n const candidate = value as { peek?: unknown; subscribe?: unknown };\n\n return typeof candidate.peek === 'function' && typeof candidate.subscribe === 'function';\n};\n","import { REACTIVE } from './runtime';\nimport type { Disposable, EffectHandle, Readable, Signal } from './types';\n\nexport type AsyncState<T> =\n | { readonly previous?: T; readonly status: 'pending' }\n | { readonly status: 'success'; readonly value: T }\n | { readonly error: unknown; readonly previous?: T; readonly status: 'error' };\n\nexport interface Resource<T> extends Readable<AsyncState<T>>, Disposable {\n reload(): void;\n}\n\nexport type ResourceOptions = {\n name?: string;\n};\n\ntype AsyncRuntime = {\n effect(callback: () => undefined | (() => void), options?: { name?: string }): EffectHandle;\n signal<T>(initial: T, options?: { name?: string }): Signal<T>;\n};\n\n/** Resource only depends on primitive runtime methods; graph binding stays private. */\nexport const createResource =\n (runtime: AsyncRuntime) =>\n <Source, Value>(\n source: () => Source,\n loader: (source: Source, context: { readonly signal: AbortSignal }) => Promise<Value>,\n options?: ResourceOptions,\n ): Resource<Value> => {\n const state = runtime.signal<AsyncState<Value>>({ status: 'pending' }, { name: options?.name });\n const reloadEpoch = runtime.signal(0);\n let active: AbortController | undefined;\n let disposed = false;\n\n const run = (): void => {\n void reloadEpoch.value;\n active?.abort();\n\n const current = state.peek();\n const previous =\n current.status === 'success' ? current.value : 'previous' in current ? current.previous : undefined;\n let input: Source;\n\n try {\n input = source();\n } catch (error) {\n state.value = previous === undefined ? { error, status: 'error' } : { error, previous, status: 'error' };\n\n return;\n }\n\n const next = new AbortController();\n\n active = next;\n state.value = previous === undefined ? { status: 'pending' } : { previous, status: 'pending' };\n\n let request: Promise<Value>;\n\n try {\n request = Promise.resolve(loader(input, { signal: next.signal }));\n } catch (error) {\n request = Promise.reject(error);\n }\n\n void request.then(\n (value) => {\n if (!disposed && !next.signal.aborted) state.value = { status: 'success', value };\n },\n (error: unknown) => {\n if (!disposed && !next.signal.aborted) {\n state.value = previous === undefined ? { error, status: 'error' } : { error, previous, status: 'error' };\n }\n },\n );\n };\n\n const stop = runtime.effect(\n () => {\n run();\n\n return () => active?.abort();\n },\n { name: options?.name },\n );\n\n stop.disposalSignal.addEventListener(\n 'abort',\n () => {\n disposed = true;\n },\n { once: true },\n );\n\n const resource: Resource<Value> = {\n get disposalSignal() {\n return stop.disposalSignal;\n },\n dispose: () => stop.dispose(),\n get disposed() {\n return disposed;\n },\n get name() {\n return state.name;\n },\n peek: () => state.peek(),\n reload: () => {\n if (disposed) return;\n\n reloadEpoch.value = reloadEpoch.peek() + 1;\n },\n subscribe: (listener) => state.subscribe(listener),\n [Symbol.dispose]() {\n this.dispose();\n },\n get value() {\n return state.value;\n },\n };\n\n Object.defineProperty(resource, REACTIVE, { value: true });\n\n return resource;\n };\n","import type { EffectHandle, Equality, Readable } from './types';\n\nexport type WatchOptions<T> = {\n equals?: Equality<T>;\n immediate?: boolean;\n name?: string;\n once?: boolean;\n};\n\ntype WatchRuntime = {\n effect(callback: () => undefined | (() => void), options?: { name?: string }): EffectHandle;\n};\n\nexport const createWatch =\n (runtime: WatchRuntime) =>\n <T>(\n source: Readable<T> | (() => T),\n callback: (value: T, previous: T | undefined) => void,\n options?: WatchOptions<T>,\n ): EffectHandle => {\n const read = typeof source === 'function' ? source : () => source.value;\n const equals = options?.equals ?? Object.is;\n let initial = true;\n let previous: T | undefined;\n // `handle` is in the temporal dead zone during the effect's initial synchronous run —\n // `runtime.effect()` calls `node.run()` before returning. Defer disposal until after\n // the constructor returns so `handle.dispose()` is reachable from inside the callback.\n let disposeAfterInit = false;\n\n const handle = runtime.effect(\n () => {\n const value = read();\n\n if (initial) {\n initial = false;\n previous = value;\n\n if (options?.immediate) {\n callback(value, undefined);\n if (options?.once) disposeAfterInit = true;\n }\n\n return;\n }\n\n if (equals(previous as T, value)) return;\n\n const oldValue = previous;\n\n previous = value;\n callback(value, oldValue);\n\n if (options?.once) handle.dispose();\n },\n { name: options?.name },\n );\n\n if (disposeAfterInit) handle.dispose();\n\n return handle;\n };\n","import { createResource, type Resource, type ResourceOptions } from './_async';\nimport { createWatch, type WatchOptions } from './_watch';\nimport { ReactiveRuntime } from './runtime';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n} from './types';\n\nexport interface Ripple {\n batch<T>(fn: () => T): T;\n computed<T>(derive: () => T, options?: ComputedOptions<T>): Readable<T>;\n createScope(name?: string): Scope;\n dispose(): void;\n readonly disposed: boolean;\n effect(callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle;\n resource<Source, Value>(\n source: () => Source,\n loader: (source: Source, context: { readonly signal: AbortSignal }) => Promise<Value>,\n options?: ResourceOptions,\n ): Resource<Value>;\n signal<T>(initial: T, options?: SignalOptions<T>): Signal<T>;\n untrack<T>(fn: () => T): T;\n watch<T>(\n source: Readable<T> | (() => T),\n callback: (value: T, previous: T | undefined) => void,\n options?: WatchOptions<T>,\n ): EffectHandle;\n}\n\n/** Creates one complete reactive graph. All factories on the object share its runtime. */\nexport const createRipple = (options?: RippleOptions): Ripple => {\n const runtime = new ReactiveRuntime(options);\n const resource = createResource(runtime);\n\n return {\n batch: runtime.batch,\n computed: runtime.computed,\n createScope: runtime.createScope,\n dispose: () => runtime.dispose(),\n get disposed() {\n return runtime.disposed;\n },\n effect: runtime.effect,\n resource,\n signal: runtime.signal,\n untrack: runtime.untrack,\n watch: createWatch(runtime),\n };\n};\n\n/**\n * The shared default reactive graph. Private — `signal`, `computed`, `effect`, `batch`,\n * `createScope`, `untrack`, `watch`, and `resource` are re-exported from the package root\n * as bound methods on this single graph instance.\n */\nexport const defaultRipple = createRipple();\n","export type { AsyncState, Resource, ResourceOptions } from './_async';\nexport { createRipple, type Ripple } from './_default';\nexport type { WatchOptions } from './_watch';\nexport {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleError,\n RippleInfiniteLoopError,\n} from './errors';\nexport { isReactive } from './runtime';\nexport type {\n Cleanup,\n ComputedOptions,\n Disposable,\n EffectHandle,\n EffectOptions,\n Equality,\n ReactiveErrorContext,\n ReactiveEvent,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nimport { defaultRipple } from './_default';\n\nexport const signal = defaultRipple.signal;\nexport const computed = defaultRipple.computed;\nexport const effect = defaultRipple.effect;\nexport const batch = defaultRipple.batch;\nexport const createScope = defaultRipple.createScope;\nexport const untrack = defaultRipple.untrack;\nexport const watch = defaultRipple.watch;\nexport const resource = defaultRipple.resource;\n"],"mappings":"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"}
|
package/dist/ripple.iife.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var Ripple=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},n=class extends t{},r=class extends t{},i=class extends t{},a=class extends t{},o=Symbol.for(`@vielzeug/ripple/reactive`),s=100,c=Symbol(`ripple.unset`),l=class{[o]=!0;dependents=new Set;name;runtime;constructor(e,t){this.runtime=e,this.name=t}subscribe(e){this.runtime.assertActive(),this.peek();let t={dependencies:new Set,onDependencyChanged:()=>this.runtime.enqueueListener(e)};return this.dependents.add(t),()=>this.dependents.delete(t)}notify(){for(let e of[...this.dependents])e.onDependencyChanged()}},u=class extends l{current;equals;constructor(e,t,n){super(e,n?.name),this.current=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.current}set value(e){if(this.runtime.assertActive(),this.equals(this.current,e))return;let t=this.current;this.current=e,this.runtime.emit({kind:`write`,name:this.name,next:e,previous:t}),this.runtime.propagate(()=>this.notify())}peek(){return this.current}update(e){this.value=e(this.current)}},d=class extends l{dependencies=new Set;computing=!1;disposed=!1;dirty=!0;current=c;derive;equals;constructor(e,t,n){super(e,n?.name),this.derive=t,this.equals=n?.equals??Object.is}get value(){return this.
|
|
1
|
+
var Ripple=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},n=class extends t{},r=class extends t{},i=class extends t{},a=class extends t{},o=Symbol.for(`@vielzeug/ripple/reactive`),s=100,c=Symbol(`ripple.unset`),l=class{[o]=!0;dependents=new Set;name;runtime;constructor(e,t){this.runtime=e,this.name=t}subscribe(e){this.runtime.assertActive(),this.peek();let t={dependencies:new Set,onDependencyChanged:()=>this.runtime.enqueueListener(e)};return this.dependents.add(t),()=>this.dependents.delete(t)}notify(){for(let e of[...this.dependents])e.onDependencyChanged()}},u=class extends l{current;equals;constructor(e,t,n){super(e,n?.name),this.current=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.current}set value(e){if(this.runtime.assertActive(),this.equals(this.current,e))return;let t=this.current;this.current=e,this.runtime.emit({kind:`write`,name:this.name,next:e,previous:t}),this.runtime.propagate(()=>this.notify())}peek(){return this.current}update(e){this.value=e(this.current)}},d=class extends l{dependencies=new Set;computing=!1;disposed=!1;dirty=!0;current=c;derive;equals;constructor(e,t,n){super(e,n?.name),this.derive=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.refresh(),this.current}peek(){return this.refresh(),this.current}onDependencyChanged(){this.disposed||(this.dirty||=!0,this.dependents.size>0&&this.refresh()&&this.notify())}dispose(){this.disposed||(this.disposed=!0,this.runtime.clearDependencies(this),this.dependents.clear())}refresh(){if(!this.dirty||this.disposed)return!1;if(this.computing)throw new n(`computed cycle detected${this.name===void 0?``:` "${this.name}"`}`);this.computing=!0,this.runtime.emit({kind:`compute`,name:this.name});try{let e=this.runtime.collect(this,this.derive),t=this.current===c||!this.equals(this.current,e);return this.current=e,this.dirty=!1,t}finally{this.computing=!1}}},f=class{disposalController=new AbortController;owned=new Set;name;isDisposed=!1;runtime;constructor(e,t){this.runtime=e,this.name=t}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}run(e){if(this.isDisposed)throw new i(`Cannot run a disposed scope.`);return this.runtime.withScope(this,e)}dispose(){if(!this.isDisposed){this.isDisposed=!0;for(let e of[...this.owned].reverse())e.dispose();this.owned.clear(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.name,node:`scope`})}}[Symbol.dispose](){this.dispose()}},p=class{dependencies=new Set;disposalController=new AbortController;cleanup;isDisposed=!1;owner;scheduled=!1;callback;options;runtime;constructor(e,t,n){this.runtime=e,this.callback=t,this.options=n}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}onDependencyChanged(){if(!this.isDisposed){if(this.options?.scheduler===`microtask`){if(this.scheduled)return;this.scheduled=!0,queueMicrotask(()=>{this.scheduled=!1,this.isDisposed||this.runtime.enqueue(this)});return}this.runtime.enqueue(this)}}run(){if(this.isDisposed)return;this.owner?.dispose(),this.owner=void 0,this.runCleanup(),this.runtime.emit({kind:`effect`,name:this.options?.name});let e=new f(this.runtime);try{let t=this.runtime.withEffectScope(e,()=>this.runtime.collectEffect(this,this.callback));this.owner=e,this.cleanup=typeof t==`function`?t:void 0}catch(t){e.dispose(),this.runtime.report(t,{kind:`effect`,name:this.options?.name})}}dispose(){this.isDisposed||(this.isDisposed=!0,this.owner?.dispose(),this.owner=void 0,this.runtime.clearDependencies(this),this.runCleanup(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.options?.name,node:`effect`}))}[Symbol.dispose](){this.dispose()}runCleanup(){let e=this.cleanup;if(this.cleanup=void 0,e!==void 0)try{e()}catch(e){this.runtime.report(e,{kind:`cleanup`,name:this.options?.name})}}},m=class{activeEffectScope;activeObserver;activeScope;isDisposed=!1;flushDepth=0;flushing=!1;pending=new Set;listeners=new Set;rootScope;observer;onError;constructor(e){this.observer=e?.observer,this.onError=e?.onError??(e=>{queueMicrotask(()=>{throw e})}),this.rootScope=new f(this,`runtime`),this.activeScope=this.rootScope}get disposed(){return this.isDisposed}signal=(e,t)=>(this.assertActive(),new u(this,e,t));computed=(e,t)=>{this.assertActive();let n=new d(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n};effect=(e,t)=>{this.assertActive();let n=new p(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n.run(),n};createScope=e=>{this.assertActive();let t=new f(this,e);return this.activeScope.owned.add(t),t};batch=e=>(this.assertActive(),this.propagate(e));untrack=e=>(this.assertActive(),this.withObserver(void 0,e));dispose(){this.isDisposed||(this.isDisposed=!0,this.rootScope.dispose())}assertActive(){if(this.isDisposed)throw new r(`Cannot use a disposed Ripple runtime.`)}track(e){let t=this.activeObserver;t?.collecting!==void 0&&t.collecting.add(e)}clearDependencies(e){for(let t of e.dependencies)t.dependents.delete(e);e.dependencies.clear()}collect(e,t){return this.collectWith(e,t,e.dependencies.size===0)}collectEffect(e,t){return this.collectWith(e,t,!0)}withEffectScope(e,t){let n=this.activeEffectScope;this.activeEffectScope=e;try{return t()}finally{this.activeEffectScope=n}}withObserver(e,t){let n=this.activeObserver;this.activeObserver=e;try{return t()}finally{this.activeObserver=n}}withScope(e,t){let n=this.activeEffectScope,r=this.activeScope;this.activeEffectScope=void 0,this.activeScope=e;try{return t()}finally{this.activeEffectScope=n,this.activeScope=r}}enqueue(e){this.pending.add(e),this.flushDepth===0&&this.flush()}enqueueListener(e){this.listeners.add(e),this.flushDepth===0&&this.flush()}propagate(e){this.flushDepth++;try{return e()}finally{this.flushDepth--,this.flushDepth===0&&this.flush()}}emit(e){try{this.observer?.(e)}catch(t){this.report(t,{kind:`observer`,name:e.name})}}report(e,t){try{this.onError(e,t)}catch(e){queueMicrotask(()=>{throw e})}}collectWith(e,t,n){let r=this.activeObserver,i=new Set;e.collecting=i,this.activeObserver=e;try{let n=t();return this.commitDependencies(e,i),n}catch(t){throw n&&this.commitDependencies(e,i),t}finally{e.collecting=void 0,this.activeObserver=r}}commitDependencies(e,t){for(let n of e.dependencies)t.has(n)||n.dependents.delete(e);for(let n of t)e.dependencies.has(n)||n.dependents.add(e);e.dependencies.clear();for(let n of t)e.dependencies.add(n)}flush(){if(this.flushing)return;this.flushing=!0;let e=0;try{for(;this.pending.size>0||this.listeners.size>0;){if(++e>s)throw new a(`infinite reactive flush (>${s} iterations)`);let t=[...this.pending],n=[...this.listeners];this.pending.clear(),this.listeners.clear();for(let e of t)e.run();for(let e of n)try{e()}catch(e){this.report(e,{kind:`listener`})}}}finally{this.flushing=!1}}},h=e=>{if(typeof e!=`object`||!e||!(o in e))return!1;let t=e;return typeof t.peek==`function`&&typeof t.subscribe==`function`},g=e=>(t,n,r)=>{let i=e.signal({status:`pending`},{name:r?.name}),a=e.signal(0),s,c=!1,l=()=>{a.value,s?.abort();let e=i.peek(),r=e.status===`success`?e.value:`previous`in e?e.previous:void 0,o;try{o=t()}catch(e){i.value=r===void 0?{error:e,status:`error`}:{error:e,previous:r,status:`error`};return}let l=new AbortController;s=l,i.value=r===void 0?{status:`pending`}:{previous:r,status:`pending`};let u;try{u=Promise.resolve(n(o,{signal:l.signal}))}catch(e){u=Promise.reject(e)}u.then(e=>{!c&&!l.signal.aborted&&(i.value={status:`success`,value:e})},e=>{!c&&!l.signal.aborted&&(i.value=r===void 0?{error:e,status:`error`}:{error:e,previous:r,status:`error`})})},u=e.effect(()=>(l(),()=>s?.abort()),{name:r?.name});u.disposalSignal.addEventListener(`abort`,()=>{c=!0},{once:!0});let d={get disposalSignal(){return u.disposalSignal},dispose:()=>u.dispose(),get disposed(){return c},get name(){return i.name},peek:()=>i.peek(),reload:()=>{c||(a.value=a.peek()+1)},subscribe:e=>i.subscribe(e),[Symbol.dispose](){this.dispose()},get value(){return i.value}};return Object.defineProperty(d,o,{value:!0}),d},_=e=>(t,n,r)=>{let i=typeof t==`function`?t:()=>t.value,a=r?.equals??Object.is,o=!0,s,c=!1,l=e.effect(()=>{let e=i();if(o){o=!1,s=e,r?.immediate&&(n(e,void 0),r?.once&&(c=!0));return}if(a(s,e))return;let t=s;s=e,n(e,t),r?.once&&l.dispose()},{name:r?.name});return c&&l.dispose(),l},v=e=>{let t=new m(e),n=g(t);return{batch:t.batch,computed:t.computed,createScope:t.createScope,dispose:()=>t.dispose(),get disposed(){return t.disposed},effect:t.effect,resource:n,signal:t.signal,untrack:t.untrack,watch:_(t)}},y=v(),b=y.signal,x=y.computed,S=y.effect,C=y.batch,w=y.createScope,T=y.untrack,E=y.watch,D=y.resource;return e.RippleComputedCycleError=n,e.RippleDisposedRuntimeError=r,e.RippleDisposedScopeError=i,e.RippleError=t,e.RippleInfiniteLoopError=a,e.batch=C,e.computed=x,e.createRipple=v,e.createScope=w,e.effect=S,e.isReactive=h,e.resource=D,e.signal=b,e.untrack=T,e.watch=E,e})({});
|
|
2
2
|
//# sourceMappingURL=ripple.iife.js.map
|
package/dist/ripple.iife.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ripple.iife.js","names":[],"sources":["../src/errors.ts","../src/runtime.ts","../src/_async.ts","../src/_watch.ts","../src/_default.ts","../src/index.ts"],"sourcesContent":["export class RippleError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class RippleComputedCycleError extends RippleError {}\nexport class RippleDisposedRuntimeError extends RippleError {}\nexport class RippleDisposedScopeError extends RippleError {}\nexport class RippleInfiniteLoopError extends RippleError {}\n","import {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleInfiniteLoopError,\n} from './errors';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n ReactiveErrorContext,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nexport const REACTIVE = Symbol.for('@vielzeug/ripple/reactive');\nconst MAX_FLUSH_ITERATIONS = 100;\nconst UNSET = Symbol('ripple.unset');\n\ntype Dependency = ReactiveNode<unknown>;\n\ntype ObserverNode = {\n collecting?: Set<Dependency>;\n readonly dependencies: Set<Dependency>;\n onDependencyChanged(): void;\n};\n\ntype Owned = {\n dispose(): void;\n};\n\nabstract class ReactiveNode<T> {\n readonly [REACTIVE] = true;\n readonly dependents = new Set<ObserverNode>();\n readonly name: string | undefined;\n protected readonly runtime: ReactiveRuntime;\n\n protected constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n abstract peek(): T;\n abstract get value(): T;\n\n subscribe(listener: () => void): Unsubscribe {\n this.runtime.assertActive();\n this.peek();\n\n const observer: ObserverNode = {\n dependencies: new Set(),\n onDependencyChanged: () => this.runtime.enqueueListener(listener),\n };\n\n this.dependents.add(observer);\n\n return () => this.dependents.delete(observer);\n }\n\n protected notify(): void {\n for (const dependent of [...this.dependents]) dependent.onDependencyChanged();\n }\n}\n\nclass SignalNode<T> extends ReactiveNode<T> implements Signal<T> {\n private current: T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, initial: T, options?: SignalOptions<T>) {\n super(runtime, options?.name);\n this.current = initial;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.runtime.track(this);\n\n return this.current;\n }\n\n set value(next: T) {\n this.runtime.assertActive();\n\n if (this.equals(this.current, next)) return;\n\n const previous = this.current;\n\n this.current = next;\n this.runtime.emit({ kind: 'write', name: this.name, next, previous });\n this.runtime.propagate(() => this.notify());\n }\n\n peek(): T {\n return this.current;\n }\n\n update(updater: (prev: T) => T): void {\n this.value = updater(this.current);\n }\n}\n\nclass ComputedNode<T> extends ReactiveNode<T> implements ObserverNode, Owned {\n readonly dependencies = new Set<Dependency>();\n private computing = false;\n private disposed = false;\n private dirty = true;\n private current: T | typeof UNSET = UNSET;\n private readonly derive: () => T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, derive: () => T, options?: ComputedOptions<T>) {\n super(runtime, options?.name);\n this.derive = derive;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.refresh();\n this.runtime.track(this);\n\n return this.current as T;\n }\n\n peek(): T {\n this.refresh();\n\n return this.current as T;\n }\n\n onDependencyChanged(): void {\n if (this.disposed) return;\n\n if (!this.dirty) this.dirty = true;\n\n if (this.dependents.size > 0 && this.refresh()) this.notify();\n }\n\n dispose(): void {\n if (this.disposed) return;\n\n this.disposed = true;\n this.runtime.clearDependencies(this);\n this.dependents.clear();\n }\n\n private refresh(): boolean {\n if (!this.dirty || this.disposed) return false;\n\n if (this.computing) {\n const label = this.name === undefined ? '' : ` \"${this.name}\"`;\n\n throw new RippleComputedCycleError(`computed cycle detected${label}`);\n }\n\n this.computing = true;\n this.runtime.emit({ kind: 'compute', name: this.name });\n\n try {\n const next = this.runtime.collect(this, this.derive);\n const changed = this.current === UNSET || !this.equals(this.current as T, next);\n\n this.current = next;\n this.dirty = false;\n\n return changed;\n } finally {\n this.computing = false;\n }\n }\n}\n\nclass ScopeNode implements Scope {\n readonly disposalController = new AbortController();\n readonly owned = new Set<Owned>();\n readonly name: string | undefined;\n private isDisposed = false;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n run<T>(fn: () => T): T {\n if (this.isDisposed) throw new RippleDisposedScopeError('Cannot run a disposed scope.');\n\n return this.runtime.withScope(this, fn);\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n for (const owned of [...this.owned].reverse()) owned.dispose();\n this.owned.clear();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.name, node: 'scope' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nclass EffectNode implements ObserverNode, EffectHandle {\n readonly dependencies = new Set<Dependency>();\n readonly disposalController = new AbortController();\n private cleanup: Cleanup | undefined;\n private isDisposed = false;\n private owner: ScopeNode | undefined;\n private scheduled = false;\n private readonly callback: () => Cleanup | undefined;\n private readonly options: EffectOptions | undefined;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, callback: () => Cleanup | undefined, options?: EffectOptions) {\n this.runtime = runtime;\n this.callback = callback;\n this.options = options;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n onDependencyChanged(): void {\n if (this.isDisposed) return;\n\n if (this.options?.scheduler === 'microtask') {\n if (this.scheduled) return;\n\n this.scheduled = true;\n queueMicrotask(() => {\n this.scheduled = false;\n\n if (!this.isDisposed) this.runtime.enqueue(this);\n });\n\n return;\n }\n\n this.runtime.enqueue(this);\n }\n\n run(): void {\n if (this.isDisposed) return;\n\n this.owner?.dispose();\n this.owner = undefined;\n this.runCleanup();\n this.runtime.emit({ kind: 'effect', name: this.options?.name });\n\n const owner = new ScopeNode(this.runtime);\n\n try {\n const cleanup = this.runtime.withEffectScope(owner, () => this.runtime.collectEffect(this, this.callback));\n\n this.owner = owner;\n this.cleanup = typeof cleanup === 'function' ? cleanup : undefined;\n } catch (error) {\n owner.dispose();\n this.runtime.report(error, { kind: 'effect', name: this.options?.name });\n }\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.owner?.dispose();\n this.owner = undefined;\n this.runtime.clearDependencies(this);\n this.runCleanup();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.options?.name, node: 'effect' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n private runCleanup(): void {\n const cleanup = this.cleanup;\n\n this.cleanup = undefined;\n\n if (cleanup === undefined) return;\n\n try {\n cleanup();\n } catch (error) {\n this.runtime.report(error, { kind: 'cleanup', name: this.options?.name });\n }\n }\n}\n\n/**\n * A runtime owns reactive graph state and lifetime. Separate instances isolate\n * applications and SSR requests without process-wide mutable hooks.\n */\nexport class ReactiveRuntime {\n private activeEffectScope: ScopeNode | undefined;\n private activeObserver: ObserverNode | undefined;\n private activeScope: ScopeNode;\n private isDisposed = false;\n private flushDepth = 0;\n private flushing = false;\n private readonly pending = new Set<EffectNode>();\n private readonly listeners = new Set<() => void>();\n private readonly rootScope: ScopeNode;\n private readonly observer: ReactiveObserver | undefined;\n private readonly onError: (error: unknown, context: ReactiveErrorContext) => void;\n\n constructor(options?: RippleOptions) {\n this.observer = options?.observer;\n this.onError =\n options?.onError ??\n ((error) => {\n queueMicrotask(() => {\n throw error;\n });\n });\n this.rootScope = new ScopeNode(this, 'runtime');\n this.activeScope = this.rootScope;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n readonly signal = <T>(initial: T, options?: SignalOptions<T>): Signal<T> => {\n this.assertActive();\n\n return new SignalNode(this, initial, options);\n };\n\n readonly computed = <T>(derive: () => T, options?: ComputedOptions<T>): Readable<T> => {\n this.assertActive();\n\n const node = new ComputedNode(this, derive, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n\n return node;\n };\n\n readonly effect = (callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle => {\n this.assertActive();\n\n const node = new EffectNode(this, callback, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n node.run();\n\n return node;\n };\n\n readonly createScope = (name?: string): Scope => {\n this.assertActive();\n\n const scope = new ScopeNode(this, name);\n\n // Scopes model explicit, caller-owned lifetimes. Unlike effects/computeds created during an\n // effect run, they deliberately attach to the enclosing scope rather than the per-run owner:\n // keyed DOM directives retain item scopes across reconciliation runs and dispose them only\n // when the item itself leaves the collection.\n this.activeScope.owned.add(scope);\n\n return scope;\n };\n\n readonly batch = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.propagate(fn);\n };\n\n readonly untrack = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.withObserver(undefined, fn);\n };\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.rootScope.dispose();\n }\n\n /** Internal node guard: disposed runtimes allow inert reads but reject graph work and mutation. */\n assertActive(): void {\n if (this.isDisposed) throw new RippleDisposedRuntimeError('Cannot use a disposed Ripple runtime.');\n }\n\n track(node: Dependency): void {\n const observer = this.activeObserver;\n\n if (observer?.collecting === undefined) return;\n\n observer.collecting.add(node);\n }\n\n clearDependencies(observer: ObserverNode): void {\n for (const dependency of observer.dependencies) dependency.dependents.delete(observer);\n observer.dependencies.clear();\n }\n\n collect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, false);\n }\n\n collectEffect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, true);\n }\n\n withEffectScope<T>(scope: ScopeNode, fn: () => T): T {\n const previous = this.activeEffectScope;\n\n this.activeEffectScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previous;\n }\n }\n\n withObserver<T>(observer: ObserverNode | undefined, fn: () => T): T {\n const previous = this.activeObserver;\n\n this.activeObserver = observer;\n\n try {\n return fn();\n } finally {\n this.activeObserver = previous;\n }\n }\n\n withScope<T>(scope: ScopeNode, fn: () => T): T {\n const previousEffectScope = this.activeEffectScope;\n const previousScope = this.activeScope;\n\n this.activeEffectScope = undefined;\n this.activeScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previousEffectScope;\n this.activeScope = previousScope;\n }\n }\n\n enqueue(effect: EffectNode): void {\n this.pending.add(effect);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n enqueueListener(listener: () => void): void {\n this.listeners.add(listener);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n propagate<T>(fn: () => T): T {\n this.flushDepth++;\n\n try {\n return fn();\n } finally {\n this.flushDepth--;\n\n if (this.flushDepth === 0) this.flush();\n }\n }\n\n emit(event: Parameters<ReactiveObserver>[0]): void {\n try {\n this.observer?.(event);\n } catch (error) {\n this.report(error, { kind: 'observer', name: event.name });\n }\n }\n\n report(error: unknown, context: ReactiveErrorContext): void {\n try {\n this.onError(error, context);\n } catch (reporterError) {\n queueMicrotask(() => {\n throw reporterError;\n });\n }\n }\n\n private collectWith<T>(observer: ObserverNode, fn: () => T, commitOnError: boolean): T {\n const previousObserver = this.activeObserver;\n const dependencies = new Set<Dependency>();\n\n observer.collecting = dependencies;\n this.activeObserver = observer;\n\n try {\n const result = fn();\n\n this.commitDependencies(observer, dependencies);\n\n return result;\n } catch (error) {\n if (commitOnError) this.commitDependencies(observer, dependencies);\n\n throw error;\n } finally {\n observer.collecting = undefined;\n this.activeObserver = previousObserver;\n }\n }\n\n private commitDependencies(observer: ObserverNode, next: Set<Dependency>): void {\n for (const dependency of observer.dependencies) {\n if (!next.has(dependency)) dependency.dependents.delete(observer);\n }\n\n for (const dependency of next) {\n if (!observer.dependencies.has(dependency)) dependency.dependents.add(observer);\n }\n\n observer.dependencies.clear();\n for (const dependency of next) observer.dependencies.add(dependency);\n }\n\n private flush(): void {\n if (this.flushing) return;\n\n this.flushing = true;\n\n let iterations = 0;\n\n try {\n while (this.pending.size > 0 || this.listeners.size > 0) {\n if (++iterations > MAX_FLUSH_ITERATIONS) {\n throw new RippleInfiniteLoopError(`infinite reactive flush (>${MAX_FLUSH_ITERATIONS} iterations)`);\n }\n\n const effects = [...this.pending];\n const listeners = [...this.listeners];\n\n this.pending.clear();\n this.listeners.clear();\n\n for (const effect of effects) effect.run();\n\n for (const listener of listeners) {\n try {\n listener();\n } catch (error) {\n this.report(error, { kind: 'listener' });\n }\n }\n }\n } finally {\n this.flushing = false;\n }\n }\n}\n\nexport const isReactive = <T>(value: T | Readable<T>): value is Readable<T> => {\n if (typeof value !== 'object' || value === null || !(REACTIVE in value)) return false;\n\n const candidate = value as { peek?: unknown; subscribe?: unknown };\n\n return typeof candidate.peek === 'function' && typeof candidate.subscribe === 'function';\n};\n","import { REACTIVE } from './runtime';\nimport type { Disposable, EffectHandle, Readable, Signal } from './types';\n\nexport type AsyncState<T> =\n | { readonly previous?: T; readonly status: 'pending' }\n | { readonly status: 'success'; readonly value: T }\n | { readonly error: unknown; readonly previous?: T; readonly status: 'error' };\n\nexport interface Resource<T> extends Readable<AsyncState<T>>, Disposable {\n reload(): void;\n}\n\nexport type ResourceOptions = {\n name?: string;\n};\n\ntype AsyncRuntime = {\n effect(callback: () => undefined | (() => void), options?: { name?: string }): EffectHandle;\n signal<T>(initial: T, options?: { name?: string }): Signal<T>;\n};\n\n/** Resource only depends on primitive runtime methods; graph binding stays private. */\nexport const createResource =\n (runtime: AsyncRuntime) =>\n <Source, Value>(\n source: () => Source,\n loader: (source: Source, context: { readonly signal: AbortSignal }) => Promise<Value>,\n options?: ResourceOptions,\n ): Resource<Value> => {\n const state = runtime.signal<AsyncState<Value>>({ status: 'pending' }, { name: options?.name });\n const reloadEpoch = runtime.signal(0);\n let active: AbortController | undefined;\n let disposed = false;\n\n const run = (): void => {\n void reloadEpoch.value;\n active?.abort();\n\n const current = state.peek();\n const previous =\n current.status === 'success' ? current.value : 'previous' in current ? current.previous : undefined;\n let input: Source;\n\n try {\n input = source();\n } catch (error) {\n state.value = previous === undefined ? { error, status: 'error' } : { error, previous, status: 'error' };\n\n return;\n }\n\n const next = new AbortController();\n\n active = next;\n state.value = previous === undefined ? { status: 'pending' } : { previous, status: 'pending' };\n\n let request: Promise<Value>;\n\n try {\n request = Promise.resolve(loader(input, { signal: next.signal }));\n } catch (error) {\n request = Promise.reject(error);\n }\n\n void request.then(\n (value) => {\n if (!disposed && !next.signal.aborted) state.value = { status: 'success', value };\n },\n (error: unknown) => {\n if (!disposed && !next.signal.aborted) {\n state.value = previous === undefined ? { error, status: 'error' } : { error, previous, status: 'error' };\n }\n },\n );\n };\n\n const stop = runtime.effect(\n () => {\n run();\n\n return () => active?.abort();\n },\n { name: options?.name },\n );\n\n stop.disposalSignal.addEventListener(\n 'abort',\n () => {\n disposed = true;\n },\n { once: true },\n );\n\n const resource: Resource<Value> = {\n get disposalSignal() {\n return stop.disposalSignal;\n },\n dispose: () => stop.dispose(),\n get disposed() {\n return disposed;\n },\n get name() {\n return state.name;\n },\n peek: () => state.peek(),\n reload: () => {\n if (disposed) return;\n\n reloadEpoch.value = reloadEpoch.peek() + 1;\n },\n subscribe: (listener) => state.subscribe(listener),\n [Symbol.dispose]() {\n this.dispose();\n },\n get value() {\n return state.value;\n },\n };\n\n Object.defineProperty(resource, REACTIVE, { value: true });\n\n return resource;\n };\n","import type { EffectHandle, Equality, Readable } from './types';\n\nexport type WatchOptions<T> = {\n equals?: Equality<T>;\n immediate?: boolean;\n name?: string;\n once?: boolean;\n};\n\ntype WatchRuntime = {\n effect(callback: () => undefined | (() => void), options?: { name?: string }): EffectHandle;\n};\n\nexport const createWatch =\n (runtime: WatchRuntime) =>\n <T>(\n source: Readable<T> | (() => T),\n callback: (value: T, previous: T | undefined) => void,\n options?: WatchOptions<T>,\n ): EffectHandle => {\n const read = typeof source === 'function' ? source : () => source.value;\n const equals = options?.equals ?? Object.is;\n let initial = true;\n let previous: T | undefined;\n // `handle` is in the temporal dead zone during the effect's initial synchronous run —\n // `runtime.effect()` calls `node.run()` before returning. Defer disposal until after\n // the constructor returns so `handle.dispose()` is reachable from inside the callback.\n let disposeAfterInit = false;\n\n const handle = runtime.effect(\n () => {\n const value = read();\n\n if (initial) {\n initial = false;\n previous = value;\n\n if (options?.immediate) {\n callback(value, undefined);\n if (options?.once) disposeAfterInit = true;\n }\n\n return;\n }\n\n if (equals(previous as T, value)) return;\n\n const oldValue = previous;\n\n previous = value;\n callback(value, oldValue);\n\n if (options?.once) handle.dispose();\n },\n { name: options?.name },\n );\n\n if (disposeAfterInit) handle.dispose();\n\n return handle;\n };\n","import { createResource, type Resource, type ResourceOptions } from './_async';\nimport { createWatch, type WatchOptions } from './_watch';\nimport { ReactiveRuntime } from './runtime';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n} from './types';\n\nexport interface Ripple {\n batch<T>(fn: () => T): T;\n computed<T>(derive: () => T, options?: ComputedOptions<T>): Readable<T>;\n createScope(name?: string): Scope;\n dispose(): void;\n readonly disposed: boolean;\n effect(callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle;\n resource<Source, Value>(\n source: () => Source,\n loader: (source: Source, context: { readonly signal: AbortSignal }) => Promise<Value>,\n options?: ResourceOptions,\n ): Resource<Value>;\n signal<T>(initial: T, options?: SignalOptions<T>): Signal<T>;\n untrack<T>(fn: () => T): T;\n watch<T>(\n source: Readable<T> | (() => T),\n callback: (value: T, previous: T | undefined) => void,\n options?: WatchOptions<T>,\n ): EffectHandle;\n}\n\n/** Creates one complete reactive graph. All factories on the object share its runtime. */\nexport const createRipple = (options?: RippleOptions): Ripple => {\n const runtime = new ReactiveRuntime(options);\n const resource = createResource(runtime);\n\n return {\n batch: runtime.batch,\n computed: runtime.computed,\n createScope: runtime.createScope,\n dispose: () => runtime.dispose(),\n get disposed() {\n return runtime.disposed;\n },\n effect: runtime.effect,\n resource,\n signal: runtime.signal,\n untrack: runtime.untrack,\n watch: createWatch(runtime),\n };\n};\n\n/**\n * The shared default reactive graph. Private — `signal`, `computed`, `effect`, `batch`,\n * `createScope`, `untrack`, `watch`, and `resource` are re-exported from the package root\n * as bound methods on this single graph instance.\n */\nexport const defaultRipple = createRipple();\n","export type { AsyncState, Resource, ResourceOptions } from './_async';\nexport { createRipple, type Ripple } from './_default';\nexport type { WatchOptions } from './_watch';\nexport {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleError,\n RippleInfiniteLoopError,\n} from './errors';\nexport { isReactive } from './runtime';\nexport type {\n Cleanup,\n ComputedOptions,\n Disposable,\n EffectHandle,\n EffectOptions,\n Equality,\n ReactiveErrorContext,\n ReactiveEvent,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nimport { defaultRipple } from './_default';\n\nexport const signal = defaultRipple.signal;\nexport const computed = defaultRipple.computed;\nexport const effect = defaultRipple.effect;\nexport const batch = defaultRipple.batch;\nexport const createScope = defaultRipple.createScope;\nexport const untrack = defaultRipple.untrack;\nexport const watch = defaultRipple.watch;\nexport const resource = defaultRipple.resource;\n"],"mappings":"qFAAA,IAAa,EAAb,cAAiC,KAAM,CACrC,YAAY,EAAiB,EAAwB,CACnD,MAAM,EAAS,CAAO,EACtB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAEa,EAAb,cAA8C,CAAY,CAAC,EAC9C,EAAb,cAAgD,CAAY,CAAC,EAChD,EAAb,cAA8C,CAAY,CAAC,EAC9C,EAAb,cAA6C,CAAY,CAAC,ECU7C,EAAW,OAAO,IAAI,2BAA2B,EACxD,EAAuB,IACvB,EAAQ,OAAO,cAAc,EAcpB,EAAf,KAA+B,CAC7B,CAAU,GAAY,GACtB,WAAsB,IAAI,IAC1B,KACA,QAEA,YAAsB,EAA0B,EAAe,CAC7D,KAAK,QAAU,EACf,KAAK,KAAO,CACd,CAKA,UAAU,EAAmC,CAC3C,KAAK,QAAQ,aAAa,EAC1B,KAAK,KAAK,EAEV,IAAM,EAAyB,CAC7B,aAAc,IAAI,IAClB,wBAA2B,KAAK,QAAQ,gBAAgB,CAAQ,CAClE,EAIA,OAFA,KAAK,WAAW,IAAI,CAAQ,MAEf,KAAK,WAAW,OAAO,CAAQ,CAC9C,CAEA,QAAyB,CACvB,IAAK,IAAM,IAAa,CAAC,GAAG,KAAK,UAAU,EAAG,EAAU,oBAAoB,CAC9E,CACF,EAEM,EAAN,cAA4B,CAAqC,CAC/D,QACA,OAEA,YAAY,EAA0B,EAAY,EAA4B,CAC5E,MAAM,EAAS,GAAS,IAAI,EAC5B,KAAK,QAAU,EACf,KAAK,OAAS,GAAS,QAAU,OAAO,EAC1C,CAEA,IAAI,OAAW,CAGb,OAFA,KAAK,QAAQ,MAAM,IAAI,EAEhB,KAAK,OACd,CAEA,IAAI,MAAM,EAAS,CAGjB,GAFA,KAAK,QAAQ,aAAa,EAEtB,KAAK,OAAO,KAAK,QAAS,CAAI,EAAG,OAErC,IAAM,EAAW,KAAK,QAEtB,KAAK,QAAU,EACf,KAAK,QAAQ,KAAK,CAAE,KAAM,QAAS,KAAM,KAAK,KAAM,OAAM,UAAS,CAAC,EACpE,KAAK,QAAQ,cAAgB,KAAK,OAAO,CAAC,CAC5C,CAEA,MAAU,CACR,OAAO,KAAK,OACd,CAEA,OAAO,EAA+B,CACpC,KAAK,MAAQ,EAAQ,KAAK,OAAO,CACnC,CACF,EAEM,EAAN,cAA8B,CAA+C,CAC3E,aAAwB,IAAI,IAC5B,UAAoB,GACpB,SAAmB,GACnB,MAAgB,GAChB,QAAoC,EACpC,OACA,OAEA,YAAY,EAA0B,EAAiB,EAA8B,CACnF,MAAM,EAAS,GAAS,IAAI,EAC5B,KAAK,OAAS,EACd,KAAK,OAAS,GAAS,QAAU,OAAO,EAC1C,CAEA,IAAI,OAAW,CAIb,OAHA,KAAK,QAAQ,EACb,KAAK,QAAQ,MAAM,IAAI,EAEhB,KAAK,OACd,CAEA,MAAU,CAGR,OAFA,KAAK,QAAQ,EAEN,KAAK,OACd,CAEA,qBAA4B,CACtB,KAAK,WAET,AAAiB,KAAK,QAAQ,GAE1B,KAAK,WAAW,KAAO,GAAK,KAAK,QAAQ,GAAG,KAAK,OAAO,EAC9D,CAEA,SAAgB,CACV,KAAK,WAET,KAAK,SAAW,GAChB,KAAK,QAAQ,kBAAkB,IAAI,EACnC,KAAK,WAAW,MAAM,EACxB,CAEA,SAA2B,CACzB,GAAI,CAAC,KAAK,OAAS,KAAK,SAAU,MAAO,GAEzC,GAAI,KAAK,UAGP,MAAM,IAAI,EAAyB,0BAFrB,KAAK,OAAS,IAAA,GAAY,GAAK,KAAK,KAAK,KAAK,IAEQ,EAGtE,KAAK,UAAY,GACjB,KAAK,QAAQ,KAAK,CAAE,KAAM,UAAW,KAAM,KAAK,IAAK,CAAC,EAEtD,GAAI,CACF,IAAM,EAAO,KAAK,QAAQ,QAAQ,KAAM,KAAK,MAAM,EAC7C,EAAU,KAAK,UAAY,GAAS,CAAC,KAAK,OAAO,KAAK,QAAc,CAAI,EAK9E,MAHA,MAAK,QAAU,EACf,KAAK,MAAQ,GAEN,CACT,QAAU,CACR,KAAK,UAAY,EACnB,CACF,CACF,EAEM,EAAN,KAAiC,CAC/B,mBAA8B,IAAI,gBAClC,MAAiB,IAAI,IACrB,KACA,WAAqB,GACrB,QAEA,YAAY,EAA0B,EAAe,CACnD,KAAK,QAAU,EACf,KAAK,KAAO,CACd,CAEA,IAAI,UAAoB,CACtB,OAAO,KAAK,UACd,CAEA,IAAI,gBAA8B,CAChC,OAAO,KAAK,mBAAmB,MACjC,CAEA,IAAO,EAAgB,CACrB,GAAI,KAAK,WAAY,MAAM,IAAI,EAAyB,8BAA8B,EAEtF,OAAO,KAAK,QAAQ,UAAU,KAAM,CAAE,CACxC,CAEA,SAAgB,CACV,SAAK,WAET,MAAK,WAAa,GAClB,IAAK,IAAM,IAAS,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,QAAQ,EAAG,EAAM,QAAQ,EAC7D,KAAK,MAAM,MAAM,EACjB,KAAK,mBAAmB,MAAM,EAC9B,KAAK,QAAQ,KAAK,CAAE,KAAM,UAAW,KAAM,KAAK,KAAM,KAAM,OAAQ,CAAC,CAJnD,CAKpB,CAEA,CAAC,OAAO,UAAiB,CACvB,KAAK,QAAQ,CACf,CACF,EAEM,EAAN,KAAuD,CACrD,aAAwB,IAAI,IAC5B,mBAA8B,IAAI,gBAClC,QACA,WAAqB,GACrB,MACA,UAAoB,GACpB,SACA,QACA,QAEA,YAAY,EAA0B,EAAqC,EAAyB,CAClG,KAAK,QAAU,EACf,KAAK,SAAW,EAChB,KAAK,QAAU,CACjB,CAEA,IAAI,UAAoB,CACtB,OAAO,KAAK,UACd,CAEA,IAAI,gBAA8B,CAChC,OAAO,KAAK,mBAAmB,MACjC,CAEA,qBAA4B,CACtB,SAAK,WAET,IAAI,KAAK,SAAS,YAAc,YAAa,CAC3C,GAAI,KAAK,UAAW,OAEpB,KAAK,UAAY,GACjB,mBAAqB,CACnB,KAAK,UAAY,GAEZ,KAAK,YAAY,KAAK,QAAQ,QAAQ,IAAI,CACjD,CAAC,EAED,MACF,CAEA,KAAK,QAAQ,QAAQ,IAAI,CAFzB,CAGF,CAEA,KAAY,CACV,GAAI,KAAK,WAAY,OAErB,KAAK,OAAO,QAAQ,EACpB,KAAK,MAAQ,IAAA,GACb,KAAK,WAAW,EAChB,KAAK,QAAQ,KAAK,CAAE,KAAM,SAAU,KAAM,KAAK,SAAS,IAAK,CAAC,EAE9D,IAAM,EAAQ,IAAI,EAAU,KAAK,OAAO,EAExC,GAAI,CACF,IAAM,EAAU,KAAK,QAAQ,gBAAgB,MAAa,KAAK,QAAQ,cAAc,KAAM,KAAK,QAAQ,CAAC,EAEzG,KAAK,MAAQ,EACb,KAAK,QAAU,OAAO,GAAY,WAAa,EAAU,IAAA,EAC3D,OAAS,EAAO,CACd,EAAM,QAAQ,EACd,KAAK,QAAQ,OAAO,EAAO,CAAE,KAAM,SAAU,KAAM,KAAK,SAAS,IAAK,CAAC,CACzE,CACF,CAEA,SAAgB,CACV,KAAK,aAET,KAAK,WAAa,GAClB,KAAK,OAAO,QAAQ,EACpB,KAAK,MAAQ,IAAA,GACb,KAAK,QAAQ,kBAAkB,IAAI,EACnC,KAAK,WAAW,EAChB,KAAK,mBAAmB,MAAM,EAC9B,KAAK,QAAQ,KAAK,CAAE,KAAM,UAAW,KAAM,KAAK,SAAS,KAAM,KAAM,QAAS,CAAC,EACjF,CAEA,CAAC,OAAO,UAAiB,CACvB,KAAK,QAAQ,CACf,CAEA,YAA2B,CACzB,IAAM,EAAU,KAAK,QAErB,QAAK,QAAU,IAAA,GAEX,IAAY,IAAA,GAEhB,GAAI,CACF,EAAQ,CACV,OAAS,EAAO,CACd,KAAK,QAAQ,OAAO,EAAO,CAAE,KAAM,UAAW,KAAM,KAAK,SAAS,IAAK,CAAC,CAC1E,CACF,CACF,EAMa,EAAb,KAA6B,CAC3B,kBACA,eACA,YACA,WAAqB,GACrB,WAAqB,EACrB,SAAmB,GACnB,QAA2B,IAAI,IAC/B,UAA6B,IAAI,IACjC,UACA,SACA,QAEA,YAAY,EAAyB,CACnC,KAAK,SAAW,GAAS,SACzB,KAAK,QACH,GAAS,UACP,GAAU,CACV,mBAAqB,CACnB,MAAM,CACR,CAAC,CACH,GACF,KAAK,UAAY,IAAI,EAAU,KAAM,SAAS,EAC9C,KAAK,YAAc,KAAK,SAC1B,CAEA,IAAI,UAAoB,CACtB,OAAO,KAAK,UACd,CAEA,QAAsB,EAAY,KAChC,KAAK,aAAa,EAEX,IAAI,EAAW,KAAM,EAAS,CAAO,GAG9C,UAAwB,EAAiB,IAA8C,CACrF,KAAK,aAAa,EAElB,IAAM,EAAO,IAAI,EAAa,KAAM,EAAQ,CAAO,EAInD,OAFC,KAAK,mBAAqB,KAAK,YAAA,CAAa,MAAM,IAAI,CAAI,EAEpD,CACT,EAEA,QAAmB,EAAqC,IAA0C,CAChG,KAAK,aAAa,EAElB,IAAM,EAAO,IAAI,EAAW,KAAM,EAAU,CAAO,EAKnD,OAHC,KAAK,mBAAqB,KAAK,YAAA,CAAa,MAAM,IAAI,CAAI,EAC3D,EAAK,IAAI,EAEF,CACT,EAEA,YAAwB,GAAyB,CAC/C,KAAK,aAAa,EAElB,IAAM,EAAQ,IAAI,EAAU,KAAM,CAAI,EAQtC,OAFA,KAAK,YAAY,MAAM,IAAI,CAAK,EAEzB,CACT,EAEA,MAAqB,IACnB,KAAK,aAAa,EAEX,KAAK,UAAU,CAAE,GAG1B,QAAuB,IACrB,KAAK,aAAa,EAEX,KAAK,aAAa,IAAA,GAAW,CAAE,GAGxC,SAAgB,CACV,KAAK,aAET,KAAK,WAAa,GAClB,KAAK,UAAU,QAAQ,EACzB,CAGA,cAAqB,CACnB,GAAI,KAAK,WAAY,MAAM,IAAI,EAA2B,uCAAuC,CACnG,CAEA,MAAM,EAAwB,CAC5B,IAAM,EAAW,KAAK,eAElB,GAAU,aAAe,IAAA,IAE7B,EAAS,WAAW,IAAI,CAAI,CAC9B,CAEA,kBAAkB,EAA8B,CAC9C,IAAK,IAAM,KAAc,EAAS,aAAc,EAAW,WAAW,OAAO,CAAQ,EACrF,EAAS,aAAa,MAAM,CAC9B,CAEA,QAAW,EAAwB,EAAgB,CACjD,OAAO,KAAK,YAAY,EAAU,EAAI,EAAK,CAC7C,CAEA,cAAiB,EAAwB,EAAgB,CACvD,OAAO,KAAK,YAAY,EAAU,EAAI,EAAI,CAC5C,CAEA,gBAAmB,EAAkB,EAAgB,CACnD,IAAM,EAAW,KAAK,kBAEtB,KAAK,kBAAoB,EAEzB,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,KAAK,kBAAoB,CAC3B,CACF,CAEA,aAAgB,EAAoC,EAAgB,CAClE,IAAM,EAAW,KAAK,eAEtB,KAAK,eAAiB,EAEtB,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,KAAK,eAAiB,CACxB,CACF,CAEA,UAAa,EAAkB,EAAgB,CAC7C,IAAM,EAAsB,KAAK,kBAC3B,EAAgB,KAAK,YAE3B,KAAK,kBAAoB,IAAA,GACzB,KAAK,YAAc,EAEnB,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,KAAK,kBAAoB,EACzB,KAAK,YAAc,CACrB,CACF,CAEA,QAAQ,EAA0B,CAChC,KAAK,QAAQ,IAAI,CAAM,EAEnB,KAAK,aAAe,GAAG,KAAK,MAAM,CACxC,CAEA,gBAAgB,EAA4B,CAC1C,KAAK,UAAU,IAAI,CAAQ,EAEvB,KAAK,aAAe,GAAG,KAAK,MAAM,CACxC,CAEA,UAAa,EAAgB,CAC3B,KAAK,aAEL,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,KAAK,aAED,KAAK,aAAe,GAAG,KAAK,MAAM,CACxC,CACF,CAEA,KAAK,EAA8C,CACjD,GAAI,CACF,KAAK,WAAW,CAAK,CACvB,OAAS,EAAO,CACd,KAAK,OAAO,EAAO,CAAE,KAAM,WAAY,KAAM,EAAM,IAAK,CAAC,CAC3D,CACF,CAEA,OAAO,EAAgB,EAAqC,CAC1D,GAAI,CACF,KAAK,QAAQ,EAAO,CAAO,CAC7B,OAAS,EAAe,CACtB,mBAAqB,CACnB,MAAM,CACR,CAAC,CACH,CACF,CAEA,YAAuB,EAAwB,EAAa,EAA2B,CACrF,IAAM,EAAmB,KAAK,eACxB,EAAe,IAAI,IAEzB,EAAS,WAAa,EACtB,KAAK,eAAiB,EAEtB,GAAI,CACF,IAAM,EAAS,EAAG,EAIlB,OAFA,KAAK,mBAAmB,EAAU,CAAY,EAEvC,CACT,OAAS,EAAO,CAGd,MAFI,GAAe,KAAK,mBAAmB,EAAU,CAAY,EAE3D,CACR,QAAU,CACR,EAAS,WAAa,IAAA,GACtB,KAAK,eAAiB,CACxB,CACF,CAEA,mBAA2B,EAAwB,EAA6B,CAC9E,IAAK,IAAM,KAAc,EAAS,aAC3B,EAAK,IAAI,CAAU,GAAG,EAAW,WAAW,OAAO,CAAQ,EAGlE,IAAK,IAAM,KAAc,EAClB,EAAS,aAAa,IAAI,CAAU,GAAG,EAAW,WAAW,IAAI,CAAQ,EAGhF,EAAS,aAAa,MAAM,EAC5B,IAAK,IAAM,KAAc,EAAM,EAAS,aAAa,IAAI,CAAU,CACrE,CAEA,OAAsB,CACpB,GAAI,KAAK,SAAU,OAEnB,KAAK,SAAW,GAEhB,IAAI,EAAa,EAEjB,GAAI,CACF,KAAO,KAAK,QAAQ,KAAO,GAAK,KAAK,UAAU,KAAO,GAAG,CACvD,GAAI,EAAE,EAAa,EACjB,MAAM,IAAI,EAAwB,6BAA6B,EAAqB,aAAa,EAGnG,IAAM,EAAU,CAAC,GAAG,KAAK,OAAO,EAC1B,EAAY,CAAC,GAAG,KAAK,SAAS,EAEpC,KAAK,QAAQ,MAAM,EACnB,KAAK,UAAU,MAAM,EAErB,IAAK,IAAM,KAAU,EAAS,EAAO,IAAI,EAEzC,IAAK,IAAM,KAAY,EACrB,GAAI,CACF,EAAS,CACX,OAAS,EAAO,CACd,KAAK,OAAO,EAAO,CAAE,KAAM,UAAW,CAAC,CACzC,CAEJ,CACF,QAAU,CACR,KAAK,SAAW,EAClB,CACF,CACF,EAEa,EAAiB,GAAiD,CAC7E,GAAI,OAAO,GAAU,WAAY,GAAkB,EAAE,KAAY,GAAQ,MAAO,GAEhF,IAAM,EAAY,EAElB,OAAO,OAAO,EAAU,MAAS,YAAc,OAAO,EAAU,WAAc,UAChF,EC1jBa,EACV,IAEC,EACA,EACA,IACoB,CACpB,IAAM,EAAQ,EAAQ,OAA0B,CAAE,OAAQ,SAAU,EAAG,CAAE,KAAM,GAAS,IAAK,CAAC,EACxF,EAAc,EAAQ,OAAO,CAAC,EAChC,EACA,EAAW,GAET,MAAkB,CACtB,EAAiB,MACjB,GAAQ,MAAM,EAEd,IAAM,EAAU,EAAM,KAAK,EACrB,EACJ,EAAQ,SAAW,UAAY,EAAQ,MAAQ,aAAc,EAAU,EAAQ,SAAW,IAAA,GACxF,EAEJ,GAAI,CACF,EAAQ,EAAO,CACjB,OAAS,EAAO,CACd,EAAM,MAAQ,IAAa,IAAA,GAAY,CAAE,QAAO,OAAQ,OAAQ,EAAI,CAAE,QAAO,WAAU,OAAQ,OAAQ,EAEvG,MACF,CAEA,IAAM,EAAO,IAAI,gBAEjB,EAAS,EACT,EAAM,MAAQ,IAAa,IAAA,GAAY,CAAE,OAAQ,SAAU,EAAI,CAAE,WAAU,OAAQ,SAAU,EAE7F,IAAI,EAEJ,GAAI,CACF,EAAU,QAAQ,QAAQ,EAAO,EAAO,CAAE,OAAQ,EAAK,MAAO,CAAC,CAAC,CAClE,OAAS,EAAO,CACd,EAAU,QAAQ,OAAO,CAAK,CAChC,CAEA,EAAa,KACV,GAAU,CACL,CAAC,GAAY,CAAC,EAAK,OAAO,UAAS,EAAM,MAAQ,CAAE,OAAQ,UAAW,OAAM,EAClF,EACC,GAAmB,CACd,CAAC,GAAY,CAAC,EAAK,OAAO,UAC5B,EAAM,MAAQ,IAAa,IAAA,GAAY,CAAE,QAAO,OAAQ,OAAQ,EAAI,CAAE,QAAO,WAAU,OAAQ,OAAQ,EAE3G,CACF,CACF,EAEM,EAAO,EAAQ,YAEjB,EAAI,MAES,GAAQ,MAAM,GAE7B,CAAE,KAAM,GAAS,IAAK,CACxB,EAEA,EAAK,eAAe,iBAClB,YACM,CACJ,EAAW,EACb,EACA,CAAE,KAAM,EAAK,CACf,EAEA,IAAM,EAA4B,CAChC,IAAI,gBAAiB,CACnB,OAAO,EAAK,cACd,EACA,YAAe,EAAK,QAAQ,EAC5B,IAAI,UAAW,CACb,OAAO,CACT,EACA,IAAI,MAAO,CACT,OAAO,EAAM,IACf,EACA,SAAY,EAAM,KAAK,EACvB,WAAc,CACR,IAEJ,EAAY,MAAQ,EAAY,KAAK,EAAI,EAC3C,EACA,UAAY,GAAa,EAAM,UAAU,CAAQ,EACjD,CAAC,OAAO,UAAW,CACjB,KAAK,QAAQ,CACf,EACA,IAAI,OAAQ,CACV,OAAO,EAAM,KACf,CACF,EAIA,OAFA,OAAO,eAAe,EAAU,EAAU,CAAE,MAAO,EAAK,CAAC,EAElD,CACT,EC7GW,EACV,IAEC,EACA,EACA,IACiB,CACjB,IAAM,EAAO,OAAO,GAAW,WAAa,MAAe,EAAO,MAC5D,EAAS,GAAS,QAAU,OAAO,GACrC,EAAU,GACV,EAIA,EAAmB,GAEjB,EAAS,EAAQ,WACf,CACJ,IAAM,EAAQ,EAAK,EAEnB,GAAI,EAAS,CACX,EAAU,GACV,EAAW,EAEP,GAAS,YACX,EAAS,EAAO,IAAA,EAAS,EACrB,GAAS,OAAM,EAAmB,KAGxC,MACF,CAEA,GAAI,EAAO,EAAe,CAAK,EAAG,OAElC,IAAM,EAAW,EAEjB,EAAW,EACX,EAAS,EAAO,CAAQ,EAEpB,GAAS,MAAM,EAAO,QAAQ,CACpC,EACA,CAAE,KAAM,GAAS,IAAK,CACxB,EAIA,OAFI,GAAkB,EAAO,QAAQ,EAE9B,CACT,ECvBW,EAAgB,GAAoC,CAC/D,IAAM,EAAU,IAAI,EAAgB,CAAO,EACrC,EAAW,EAAe,CAAO,EAEvC,MAAO,CACL,MAAO,EAAQ,MACf,SAAU,EAAQ,SAClB,YAAa,EAAQ,YACrB,YAAe,EAAQ,QAAQ,EAC/B,IAAI,UAAW,CACb,OAAO,EAAQ,QACjB,EACA,OAAQ,EAAQ,OAChB,WACA,OAAQ,EAAQ,OAChB,QAAS,EAAQ,QACjB,MAAO,EAAY,CAAO,CAC5B,CACF,EAOa,EAAgB,EAAa,EC/B7B,EAAS,EAAc,OACvB,EAAW,EAAc,SACzB,EAAS,EAAc,OACvB,EAAQ,EAAc,MACtB,EAAc,EAAc,YAC5B,EAAU,EAAc,QACxB,EAAQ,EAAc,MACtB,EAAW,EAAc"}
|
|
1
|
+
{"version":3,"file":"ripple.iife.js","names":[],"sources":["../src/errors.ts","../src/runtime.ts","../src/_async.ts","../src/_watch.ts","../src/_default.ts","../src/index.ts"],"sourcesContent":["export class RippleError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class RippleComputedCycleError extends RippleError {}\nexport class RippleDisposedRuntimeError extends RippleError {}\nexport class RippleDisposedScopeError extends RippleError {}\nexport class RippleInfiniteLoopError extends RippleError {}\n","import {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleInfiniteLoopError,\n} from './errors';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n ReactiveErrorContext,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nexport const REACTIVE = Symbol.for('@vielzeug/ripple/reactive');\nconst MAX_FLUSH_ITERATIONS = 100;\nconst UNSET = Symbol('ripple.unset');\n\ntype Dependency = ReactiveNode<unknown>;\n\ntype ObserverNode = {\n collecting?: Set<Dependency>;\n readonly dependencies: Set<Dependency>;\n onDependencyChanged(): void;\n};\n\ntype Owned = {\n dispose(): void;\n};\n\nabstract class ReactiveNode<T> {\n readonly [REACTIVE] = true;\n readonly dependents = new Set<ObserverNode>();\n readonly name: string | undefined;\n protected readonly runtime: ReactiveRuntime;\n\n protected constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n abstract peek(): T;\n abstract get value(): T;\n\n subscribe(listener: () => void): Unsubscribe {\n this.runtime.assertActive();\n this.peek();\n\n const observer: ObserverNode = {\n dependencies: new Set(),\n onDependencyChanged: () => this.runtime.enqueueListener(listener),\n };\n\n this.dependents.add(observer);\n\n return () => this.dependents.delete(observer);\n }\n\n protected notify(): void {\n for (const dependent of [...this.dependents]) dependent.onDependencyChanged();\n }\n}\n\nclass SignalNode<T> extends ReactiveNode<T> implements Signal<T> {\n private current: T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, initial: T, options?: SignalOptions<T>) {\n super(runtime, options?.name);\n this.current = initial;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.runtime.track(this);\n\n return this.current;\n }\n\n set value(next: T) {\n this.runtime.assertActive();\n\n if (this.equals(this.current, next)) return;\n\n const previous = this.current;\n\n this.current = next;\n this.runtime.emit({ kind: 'write', name: this.name, next, previous });\n this.runtime.propagate(() => this.notify());\n }\n\n peek(): T {\n return this.current;\n }\n\n update(updater: (prev: T) => T): void {\n this.value = updater(this.current);\n }\n}\n\nclass ComputedNode<T> extends ReactiveNode<T> implements ObserverNode, Owned {\n readonly dependencies = new Set<Dependency>();\n private computing = false;\n private disposed = false;\n private dirty = true;\n private current: T | typeof UNSET = UNSET;\n private readonly derive: () => T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, derive: () => T, options?: ComputedOptions<T>) {\n super(runtime, options?.name);\n this.derive = derive;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n // Track before refresh: if refresh throws, the consumer still depends on\n // this computed and must be notified when a dependency change might let it\n // succeed. Without this, a first-run failure permanently severs the\n // consumer from the computed.\n this.runtime.track(this);\n this.refresh();\n\n return this.current as T;\n }\n\n peek(): T {\n this.refresh();\n\n return this.current as T;\n }\n\n onDependencyChanged(): void {\n if (this.disposed) return;\n\n if (!this.dirty) this.dirty = true;\n\n if (this.dependents.size > 0 && this.refresh()) this.notify();\n }\n\n dispose(): void {\n if (this.disposed) return;\n\n this.disposed = true;\n this.runtime.clearDependencies(this);\n this.dependents.clear();\n }\n\n private refresh(): boolean {\n if (!this.dirty || this.disposed) return false;\n\n if (this.computing) {\n const label = this.name === undefined ? '' : ` \"${this.name}\"`;\n\n throw new RippleComputedCycleError(`computed cycle detected${label}`);\n }\n\n this.computing = true;\n this.runtime.emit({ kind: 'compute', name: this.name });\n\n try {\n const next = this.runtime.collect(this, this.derive);\n const changed = this.current === UNSET || !this.equals(this.current as T, next);\n\n this.current = next;\n this.dirty = false;\n\n return changed;\n } finally {\n this.computing = false;\n }\n }\n}\n\nclass ScopeNode implements Scope {\n readonly disposalController = new AbortController();\n readonly owned = new Set<Owned>();\n readonly name: string | undefined;\n private isDisposed = false;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n run<T>(fn: () => T): T {\n if (this.isDisposed) throw new RippleDisposedScopeError('Cannot run a disposed scope.');\n\n return this.runtime.withScope(this, fn);\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n for (const owned of [...this.owned].reverse()) owned.dispose();\n this.owned.clear();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.name, node: 'scope' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nclass EffectNode implements ObserverNode, EffectHandle {\n readonly dependencies = new Set<Dependency>();\n readonly disposalController = new AbortController();\n private cleanup: Cleanup | undefined;\n private isDisposed = false;\n private owner: ScopeNode | undefined;\n private scheduled = false;\n private readonly callback: () => Cleanup | undefined;\n private readonly options: EffectOptions | undefined;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, callback: () => Cleanup | undefined, options?: EffectOptions) {\n this.runtime = runtime;\n this.callback = callback;\n this.options = options;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n onDependencyChanged(): void {\n if (this.isDisposed) return;\n\n if (this.options?.scheduler === 'microtask') {\n if (this.scheduled) return;\n\n this.scheduled = true;\n queueMicrotask(() => {\n this.scheduled = false;\n\n if (!this.isDisposed) this.runtime.enqueue(this);\n });\n\n return;\n }\n\n this.runtime.enqueue(this);\n }\n\n run(): void {\n if (this.isDisposed) return;\n\n this.owner?.dispose();\n this.owner = undefined;\n this.runCleanup();\n this.runtime.emit({ kind: 'effect', name: this.options?.name });\n\n const owner = new ScopeNode(this.runtime);\n\n try {\n const cleanup = this.runtime.withEffectScope(owner, () => this.runtime.collectEffect(this, this.callback));\n\n this.owner = owner;\n this.cleanup = typeof cleanup === 'function' ? cleanup : undefined;\n } catch (error) {\n owner.dispose();\n this.runtime.report(error, { kind: 'effect', name: this.options?.name });\n }\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.owner?.dispose();\n this.owner = undefined;\n this.runtime.clearDependencies(this);\n this.runCleanup();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.options?.name, node: 'effect' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n private runCleanup(): void {\n const cleanup = this.cleanup;\n\n this.cleanup = undefined;\n\n if (cleanup === undefined) return;\n\n try {\n cleanup();\n } catch (error) {\n this.runtime.report(error, { kind: 'cleanup', name: this.options?.name });\n }\n }\n}\n\n/**\n * A runtime owns reactive graph state and lifetime. Separate instances isolate\n * applications and SSR requests without process-wide mutable hooks.\n */\nexport class ReactiveRuntime {\n private activeEffectScope: ScopeNode | undefined;\n private activeObserver: ObserverNode | undefined;\n private activeScope: ScopeNode;\n private isDisposed = false;\n private flushDepth = 0;\n private flushing = false;\n private readonly pending = new Set<EffectNode>();\n private readonly listeners = new Set<() => void>();\n private readonly rootScope: ScopeNode;\n private readonly observer: ReactiveObserver | undefined;\n private readonly onError: (error: unknown, context: ReactiveErrorContext) => void;\n\n constructor(options?: RippleOptions) {\n this.observer = options?.observer;\n this.onError =\n options?.onError ??\n ((error) => {\n queueMicrotask(() => {\n throw error;\n });\n });\n this.rootScope = new ScopeNode(this, 'runtime');\n this.activeScope = this.rootScope;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n readonly signal = <T>(initial: T, options?: SignalOptions<T>): Signal<T> => {\n this.assertActive();\n\n return new SignalNode(this, initial, options);\n };\n\n readonly computed = <T>(derive: () => T, options?: ComputedOptions<T>): Readable<T> => {\n this.assertActive();\n\n const node = new ComputedNode(this, derive, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n\n return node;\n };\n\n readonly effect = (callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle => {\n this.assertActive();\n\n const node = new EffectNode(this, callback, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n node.run();\n\n return node;\n };\n\n readonly createScope = (name?: string): Scope => {\n this.assertActive();\n\n const scope = new ScopeNode(this, name);\n\n // Scopes model explicit, caller-owned lifetimes. Unlike effects/computeds created during an\n // effect run, they deliberately attach to the enclosing scope rather than the per-run owner:\n // keyed DOM directives retain item scopes across reconciliation runs and dispose them only\n // when the item itself leaves the collection.\n this.activeScope.owned.add(scope);\n\n return scope;\n };\n\n readonly batch = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.propagate(fn);\n };\n\n readonly untrack = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.withObserver(undefined, fn);\n };\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.rootScope.dispose();\n }\n\n /** Internal node guard: disposed runtimes allow inert reads but reject graph work and mutation. */\n assertActive(): void {\n if (this.isDisposed) throw new RippleDisposedRuntimeError('Cannot use a disposed Ripple runtime.');\n }\n\n track(node: Dependency): void {\n const observer = this.activeObserver;\n\n if (observer?.collecting === undefined) return;\n\n observer.collecting.add(node);\n }\n\n clearDependencies(observer: ObserverNode): void {\n for (const dependency of observer.dependencies) dependency.dependents.delete(observer);\n observer.dependencies.clear();\n }\n\n collect<T>(observer: ObserverNode, fn: () => T): T {\n // On first run (no prior dependencies), commit partial dependencies even if\n // derive throws — otherwise the computed would have zero dependencies and never\n // be notified when its source changes, permanently stuck until a manual read.\n // On subsequent runs, keep previous dependencies (tested behavior).\n return this.collectWith(observer, fn, observer.dependencies.size === 0);\n }\n\n collectEffect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, true);\n }\n\n withEffectScope<T>(scope: ScopeNode, fn: () => T): T {\n const previous = this.activeEffectScope;\n\n this.activeEffectScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previous;\n }\n }\n\n withObserver<T>(observer: ObserverNode | undefined, fn: () => T): T {\n const previous = this.activeObserver;\n\n this.activeObserver = observer;\n\n try {\n return fn();\n } finally {\n this.activeObserver = previous;\n }\n }\n\n withScope<T>(scope: ScopeNode, fn: () => T): T {\n const previousEffectScope = this.activeEffectScope;\n const previousScope = this.activeScope;\n\n this.activeEffectScope = undefined;\n this.activeScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previousEffectScope;\n this.activeScope = previousScope;\n }\n }\n\n enqueue(effect: EffectNode): void {\n this.pending.add(effect);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n enqueueListener(listener: () => void): void {\n this.listeners.add(listener);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n propagate<T>(fn: () => T): T {\n this.flushDepth++;\n\n try {\n return fn();\n } finally {\n this.flushDepth--;\n\n if (this.flushDepth === 0) this.flush();\n }\n }\n\n emit(event: Parameters<ReactiveObserver>[0]): void {\n try {\n this.observer?.(event);\n } catch (error) {\n this.report(error, { kind: 'observer', name: event.name });\n }\n }\n\n report(error: unknown, context: ReactiveErrorContext): void {\n try {\n this.onError(error, context);\n } catch (reporterError) {\n queueMicrotask(() => {\n throw reporterError;\n });\n }\n }\n\n private collectWith<T>(observer: ObserverNode, fn: () => T, commitOnError: boolean): T {\n const previousObserver = this.activeObserver;\n const dependencies = new Set<Dependency>();\n\n observer.collecting = dependencies;\n this.activeObserver = observer;\n\n try {\n const result = fn();\n\n this.commitDependencies(observer, dependencies);\n\n return result;\n } catch (error) {\n if (commitOnError) this.commitDependencies(observer, dependencies);\n\n throw error;\n } finally {\n observer.collecting = undefined;\n this.activeObserver = previousObserver;\n }\n }\n\n private commitDependencies(observer: ObserverNode, next: Set<Dependency>): void {\n for (const dependency of observer.dependencies) {\n if (!next.has(dependency)) dependency.dependents.delete(observer);\n }\n\n for (const dependency of next) {\n if (!observer.dependencies.has(dependency)) dependency.dependents.add(observer);\n }\n\n observer.dependencies.clear();\n for (const dependency of next) observer.dependencies.add(dependency);\n }\n\n private flush(): void {\n if (this.flushing) return;\n\n this.flushing = true;\n\n let iterations = 0;\n\n try {\n while (this.pending.size > 0 || this.listeners.size > 0) {\n if (++iterations > MAX_FLUSH_ITERATIONS) {\n throw new RippleInfiniteLoopError(`infinite reactive flush (>${MAX_FLUSH_ITERATIONS} iterations)`);\n }\n\n const effects = [...this.pending];\n const listeners = [...this.listeners];\n\n this.pending.clear();\n this.listeners.clear();\n\n for (const effect of effects) effect.run();\n\n for (const listener of listeners) {\n try {\n listener();\n } catch (error) {\n this.report(error, { kind: 'listener' });\n }\n }\n }\n } finally {\n this.flushing = false;\n }\n }\n}\n\nexport const isReactive = <T>(value: T | Readable<T>): value is Readable<T> => {\n if (typeof value !== 'object' || value === null || !(REACTIVE in value)) return false;\n\n const candidate = value as { peek?: unknown; subscribe?: unknown };\n\n return typeof candidate.peek === 'function' && typeof candidate.subscribe === 'function';\n};\n","import { REACTIVE } from './runtime';\nimport type { Disposable, EffectHandle, Readable, Signal } from './types';\n\nexport type AsyncState<T> =\n | { readonly previous?: T; readonly status: 'pending' }\n | { readonly status: 'success'; readonly value: T }\n | { readonly error: unknown; readonly previous?: T; readonly status: 'error' };\n\nexport interface Resource<T> extends Readable<AsyncState<T>>, Disposable {\n reload(): void;\n}\n\nexport type ResourceOptions = {\n name?: string;\n};\n\ntype AsyncRuntime = {\n effect(callback: () => undefined | (() => void), options?: { name?: string }): EffectHandle;\n signal<T>(initial: T, options?: { name?: string }): Signal<T>;\n};\n\n/** Resource only depends on primitive runtime methods; graph binding stays private. */\nexport const createResource =\n (runtime: AsyncRuntime) =>\n <Source, Value>(\n source: () => Source,\n loader: (source: Source, context: { readonly signal: AbortSignal }) => Promise<Value>,\n options?: ResourceOptions,\n ): Resource<Value> => {\n const state = runtime.signal<AsyncState<Value>>({ status: 'pending' }, { name: options?.name });\n const reloadEpoch = runtime.signal(0);\n let active: AbortController | undefined;\n let disposed = false;\n\n const run = (): void => {\n void reloadEpoch.value;\n active?.abort();\n\n const current = state.peek();\n const previous =\n current.status === 'success' ? current.value : 'previous' in current ? current.previous : undefined;\n let input: Source;\n\n try {\n input = source();\n } catch (error) {\n state.value = previous === undefined ? { error, status: 'error' } : { error, previous, status: 'error' };\n\n return;\n }\n\n const next = new AbortController();\n\n active = next;\n state.value = previous === undefined ? { status: 'pending' } : { previous, status: 'pending' };\n\n let request: Promise<Value>;\n\n try {\n request = Promise.resolve(loader(input, { signal: next.signal }));\n } catch (error) {\n request = Promise.reject(error);\n }\n\n void request.then(\n (value) => {\n if (!disposed && !next.signal.aborted) state.value = { status: 'success', value };\n },\n (error: unknown) => {\n if (!disposed && !next.signal.aborted) {\n state.value = previous === undefined ? { error, status: 'error' } : { error, previous, status: 'error' };\n }\n },\n );\n };\n\n const stop = runtime.effect(\n () => {\n run();\n\n return () => active?.abort();\n },\n { name: options?.name },\n );\n\n stop.disposalSignal.addEventListener(\n 'abort',\n () => {\n disposed = true;\n },\n { once: true },\n );\n\n const resource: Resource<Value> = {\n get disposalSignal() {\n return stop.disposalSignal;\n },\n dispose: () => stop.dispose(),\n get disposed() {\n return disposed;\n },\n get name() {\n return state.name;\n },\n peek: () => state.peek(),\n reload: () => {\n if (disposed) return;\n\n reloadEpoch.value = reloadEpoch.peek() + 1;\n },\n subscribe: (listener) => state.subscribe(listener),\n [Symbol.dispose]() {\n this.dispose();\n },\n get value() {\n return state.value;\n },\n };\n\n Object.defineProperty(resource, REACTIVE, { value: true });\n\n return resource;\n };\n","import type { EffectHandle, Equality, Readable } from './types';\n\nexport type WatchOptions<T> = {\n equals?: Equality<T>;\n immediate?: boolean;\n name?: string;\n once?: boolean;\n};\n\ntype WatchRuntime = {\n effect(callback: () => undefined | (() => void), options?: { name?: string }): EffectHandle;\n};\n\nexport const createWatch =\n (runtime: WatchRuntime) =>\n <T>(\n source: Readable<T> | (() => T),\n callback: (value: T, previous: T | undefined) => void,\n options?: WatchOptions<T>,\n ): EffectHandle => {\n const read = typeof source === 'function' ? source : () => source.value;\n const equals = options?.equals ?? Object.is;\n let initial = true;\n let previous: T | undefined;\n // `handle` is in the temporal dead zone during the effect's initial synchronous run —\n // `runtime.effect()` calls `node.run()` before returning. Defer disposal until after\n // the constructor returns so `handle.dispose()` is reachable from inside the callback.\n let disposeAfterInit = false;\n\n const handle = runtime.effect(\n () => {\n const value = read();\n\n if (initial) {\n initial = false;\n previous = value;\n\n if (options?.immediate) {\n callback(value, undefined);\n if (options?.once) disposeAfterInit = true;\n }\n\n return;\n }\n\n if (equals(previous as T, value)) return;\n\n const oldValue = previous;\n\n previous = value;\n callback(value, oldValue);\n\n if (options?.once) handle.dispose();\n },\n { name: options?.name },\n );\n\n if (disposeAfterInit) handle.dispose();\n\n return handle;\n };\n","import { createResource, type Resource, type ResourceOptions } from './_async';\nimport { createWatch, type WatchOptions } from './_watch';\nimport { ReactiveRuntime } from './runtime';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n} from './types';\n\nexport interface Ripple {\n batch<T>(fn: () => T): T;\n computed<T>(derive: () => T, options?: ComputedOptions<T>): Readable<T>;\n createScope(name?: string): Scope;\n dispose(): void;\n readonly disposed: boolean;\n effect(callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle;\n resource<Source, Value>(\n source: () => Source,\n loader: (source: Source, context: { readonly signal: AbortSignal }) => Promise<Value>,\n options?: ResourceOptions,\n ): Resource<Value>;\n signal<T>(initial: T, options?: SignalOptions<T>): Signal<T>;\n untrack<T>(fn: () => T): T;\n watch<T>(\n source: Readable<T> | (() => T),\n callback: (value: T, previous: T | undefined) => void,\n options?: WatchOptions<T>,\n ): EffectHandle;\n}\n\n/** Creates one complete reactive graph. All factories on the object share its runtime. */\nexport const createRipple = (options?: RippleOptions): Ripple => {\n const runtime = new ReactiveRuntime(options);\n const resource = createResource(runtime);\n\n return {\n batch: runtime.batch,\n computed: runtime.computed,\n createScope: runtime.createScope,\n dispose: () => runtime.dispose(),\n get disposed() {\n return runtime.disposed;\n },\n effect: runtime.effect,\n resource,\n signal: runtime.signal,\n untrack: runtime.untrack,\n watch: createWatch(runtime),\n };\n};\n\n/**\n * The shared default reactive graph. Private — `signal`, `computed`, `effect`, `batch`,\n * `createScope`, `untrack`, `watch`, and `resource` are re-exported from the package root\n * as bound methods on this single graph instance.\n */\nexport const defaultRipple = createRipple();\n","export type { AsyncState, Resource, ResourceOptions } from './_async';\nexport { createRipple, type Ripple } from './_default';\nexport type { WatchOptions } from './_watch';\nexport {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleError,\n RippleInfiniteLoopError,\n} from './errors';\nexport { isReactive } from './runtime';\nexport type {\n Cleanup,\n ComputedOptions,\n Disposable,\n EffectHandle,\n EffectOptions,\n Equality,\n ReactiveErrorContext,\n ReactiveEvent,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nimport { defaultRipple } from './_default';\n\nexport const signal = defaultRipple.signal;\nexport const computed = defaultRipple.computed;\nexport const effect = defaultRipple.effect;\nexport const batch = defaultRipple.batch;\nexport const createScope = defaultRipple.createScope;\nexport const untrack = defaultRipple.untrack;\nexport const watch = defaultRipple.watch;\nexport const resource = defaultRipple.resource;\n"],"mappings":"qFAAA,IAAa,EAAb,cAAiC,KAAM,CACrC,YAAY,EAAiB,EAAwB,CACnD,MAAM,EAAS,CAAO,EACtB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAEa,EAAb,cAA8C,CAAY,CAAC,EAC9C,EAAb,cAAgD,CAAY,CAAC,EAChD,EAAb,cAA8C,CAAY,CAAC,EAC9C,EAAb,cAA6C,CAAY,CAAC,ECU7C,EAAW,OAAO,IAAI,2BAA2B,EACxD,EAAuB,IACvB,EAAQ,OAAO,cAAc,EAcpB,EAAf,KAA+B,CAC7B,CAAU,GAAY,GACtB,WAAsB,IAAI,IAC1B,KACA,QAEA,YAAsB,EAA0B,EAAe,CAC7D,KAAK,QAAU,EACf,KAAK,KAAO,CACd,CAKA,UAAU,EAAmC,CAC3C,KAAK,QAAQ,aAAa,EAC1B,KAAK,KAAK,EAEV,IAAM,EAAyB,CAC7B,aAAc,IAAI,IAClB,wBAA2B,KAAK,QAAQ,gBAAgB,CAAQ,CAClE,EAIA,OAFA,KAAK,WAAW,IAAI,CAAQ,MAEf,KAAK,WAAW,OAAO,CAAQ,CAC9C,CAEA,QAAyB,CACvB,IAAK,IAAM,IAAa,CAAC,GAAG,KAAK,UAAU,EAAG,EAAU,oBAAoB,CAC9E,CACF,EAEM,EAAN,cAA4B,CAAqC,CAC/D,QACA,OAEA,YAAY,EAA0B,EAAY,EAA4B,CAC5E,MAAM,EAAS,GAAS,IAAI,EAC5B,KAAK,QAAU,EACf,KAAK,OAAS,GAAS,QAAU,OAAO,EAC1C,CAEA,IAAI,OAAW,CAGb,OAFA,KAAK,QAAQ,MAAM,IAAI,EAEhB,KAAK,OACd,CAEA,IAAI,MAAM,EAAS,CAGjB,GAFA,KAAK,QAAQ,aAAa,EAEtB,KAAK,OAAO,KAAK,QAAS,CAAI,EAAG,OAErC,IAAM,EAAW,KAAK,QAEtB,KAAK,QAAU,EACf,KAAK,QAAQ,KAAK,CAAE,KAAM,QAAS,KAAM,KAAK,KAAM,OAAM,UAAS,CAAC,EACpE,KAAK,QAAQ,cAAgB,KAAK,OAAO,CAAC,CAC5C,CAEA,MAAU,CACR,OAAO,KAAK,OACd,CAEA,OAAO,EAA+B,CACpC,KAAK,MAAQ,EAAQ,KAAK,OAAO,CACnC,CACF,EAEM,EAAN,cAA8B,CAA+C,CAC3E,aAAwB,IAAI,IAC5B,UAAoB,GACpB,SAAmB,GACnB,MAAgB,GAChB,QAAoC,EACpC,OACA,OAEA,YAAY,EAA0B,EAAiB,EAA8B,CACnF,MAAM,EAAS,GAAS,IAAI,EAC5B,KAAK,OAAS,EACd,KAAK,OAAS,GAAS,QAAU,OAAO,EAC1C,CAEA,IAAI,OAAW,CAQb,OAHA,KAAK,QAAQ,MAAM,IAAI,EACvB,KAAK,QAAQ,EAEN,KAAK,OACd,CAEA,MAAU,CAGR,OAFA,KAAK,QAAQ,EAEN,KAAK,OACd,CAEA,qBAA4B,CACtB,KAAK,WAET,AAAiB,KAAK,QAAQ,GAE1B,KAAK,WAAW,KAAO,GAAK,KAAK,QAAQ,GAAG,KAAK,OAAO,EAC9D,CAEA,SAAgB,CACV,KAAK,WAET,KAAK,SAAW,GAChB,KAAK,QAAQ,kBAAkB,IAAI,EACnC,KAAK,WAAW,MAAM,EACxB,CAEA,SAA2B,CACzB,GAAI,CAAC,KAAK,OAAS,KAAK,SAAU,MAAO,GAEzC,GAAI,KAAK,UAGP,MAAM,IAAI,EAAyB,0BAFrB,KAAK,OAAS,IAAA,GAAY,GAAK,KAAK,KAAK,KAAK,IAEQ,EAGtE,KAAK,UAAY,GACjB,KAAK,QAAQ,KAAK,CAAE,KAAM,UAAW,KAAM,KAAK,IAAK,CAAC,EAEtD,GAAI,CACF,IAAM,EAAO,KAAK,QAAQ,QAAQ,KAAM,KAAK,MAAM,EAC7C,EAAU,KAAK,UAAY,GAAS,CAAC,KAAK,OAAO,KAAK,QAAc,CAAI,EAK9E,MAHA,MAAK,QAAU,EACf,KAAK,MAAQ,GAEN,CACT,QAAU,CACR,KAAK,UAAY,EACnB,CACF,CACF,EAEM,EAAN,KAAiC,CAC/B,mBAA8B,IAAI,gBAClC,MAAiB,IAAI,IACrB,KACA,WAAqB,GACrB,QAEA,YAAY,EAA0B,EAAe,CACnD,KAAK,QAAU,EACf,KAAK,KAAO,CACd,CAEA,IAAI,UAAoB,CACtB,OAAO,KAAK,UACd,CAEA,IAAI,gBAA8B,CAChC,OAAO,KAAK,mBAAmB,MACjC,CAEA,IAAO,EAAgB,CACrB,GAAI,KAAK,WAAY,MAAM,IAAI,EAAyB,8BAA8B,EAEtF,OAAO,KAAK,QAAQ,UAAU,KAAM,CAAE,CACxC,CAEA,SAAgB,CACV,SAAK,WAET,MAAK,WAAa,GAClB,IAAK,IAAM,IAAS,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,QAAQ,EAAG,EAAM,QAAQ,EAC7D,KAAK,MAAM,MAAM,EACjB,KAAK,mBAAmB,MAAM,EAC9B,KAAK,QAAQ,KAAK,CAAE,KAAM,UAAW,KAAM,KAAK,KAAM,KAAM,OAAQ,CAAC,CAJnD,CAKpB,CAEA,CAAC,OAAO,UAAiB,CACvB,KAAK,QAAQ,CACf,CACF,EAEM,EAAN,KAAuD,CACrD,aAAwB,IAAI,IAC5B,mBAA8B,IAAI,gBAClC,QACA,WAAqB,GACrB,MACA,UAAoB,GACpB,SACA,QACA,QAEA,YAAY,EAA0B,EAAqC,EAAyB,CAClG,KAAK,QAAU,EACf,KAAK,SAAW,EAChB,KAAK,QAAU,CACjB,CAEA,IAAI,UAAoB,CACtB,OAAO,KAAK,UACd,CAEA,IAAI,gBAA8B,CAChC,OAAO,KAAK,mBAAmB,MACjC,CAEA,qBAA4B,CACtB,SAAK,WAET,IAAI,KAAK,SAAS,YAAc,YAAa,CAC3C,GAAI,KAAK,UAAW,OAEpB,KAAK,UAAY,GACjB,mBAAqB,CACnB,KAAK,UAAY,GAEZ,KAAK,YAAY,KAAK,QAAQ,QAAQ,IAAI,CACjD,CAAC,EAED,MACF,CAEA,KAAK,QAAQ,QAAQ,IAAI,CAFzB,CAGF,CAEA,KAAY,CACV,GAAI,KAAK,WAAY,OAErB,KAAK,OAAO,QAAQ,EACpB,KAAK,MAAQ,IAAA,GACb,KAAK,WAAW,EAChB,KAAK,QAAQ,KAAK,CAAE,KAAM,SAAU,KAAM,KAAK,SAAS,IAAK,CAAC,EAE9D,IAAM,EAAQ,IAAI,EAAU,KAAK,OAAO,EAExC,GAAI,CACF,IAAM,EAAU,KAAK,QAAQ,gBAAgB,MAAa,KAAK,QAAQ,cAAc,KAAM,KAAK,QAAQ,CAAC,EAEzG,KAAK,MAAQ,EACb,KAAK,QAAU,OAAO,GAAY,WAAa,EAAU,IAAA,EAC3D,OAAS,EAAO,CACd,EAAM,QAAQ,EACd,KAAK,QAAQ,OAAO,EAAO,CAAE,KAAM,SAAU,KAAM,KAAK,SAAS,IAAK,CAAC,CACzE,CACF,CAEA,SAAgB,CACV,KAAK,aAET,KAAK,WAAa,GAClB,KAAK,OAAO,QAAQ,EACpB,KAAK,MAAQ,IAAA,GACb,KAAK,QAAQ,kBAAkB,IAAI,EACnC,KAAK,WAAW,EAChB,KAAK,mBAAmB,MAAM,EAC9B,KAAK,QAAQ,KAAK,CAAE,KAAM,UAAW,KAAM,KAAK,SAAS,KAAM,KAAM,QAAS,CAAC,EACjF,CAEA,CAAC,OAAO,UAAiB,CACvB,KAAK,QAAQ,CACf,CAEA,YAA2B,CACzB,IAAM,EAAU,KAAK,QAErB,QAAK,QAAU,IAAA,GAEX,IAAY,IAAA,GAEhB,GAAI,CACF,EAAQ,CACV,OAAS,EAAO,CACd,KAAK,QAAQ,OAAO,EAAO,CAAE,KAAM,UAAW,KAAM,KAAK,SAAS,IAAK,CAAC,CAC1E,CACF,CACF,EAMa,EAAb,KAA6B,CAC3B,kBACA,eACA,YACA,WAAqB,GACrB,WAAqB,EACrB,SAAmB,GACnB,QAA2B,IAAI,IAC/B,UAA6B,IAAI,IACjC,UACA,SACA,QAEA,YAAY,EAAyB,CACnC,KAAK,SAAW,GAAS,SACzB,KAAK,QACH,GAAS,UACP,GAAU,CACV,mBAAqB,CACnB,MAAM,CACR,CAAC,CACH,GACF,KAAK,UAAY,IAAI,EAAU,KAAM,SAAS,EAC9C,KAAK,YAAc,KAAK,SAC1B,CAEA,IAAI,UAAoB,CACtB,OAAO,KAAK,UACd,CAEA,QAAsB,EAAY,KAChC,KAAK,aAAa,EAEX,IAAI,EAAW,KAAM,EAAS,CAAO,GAG9C,UAAwB,EAAiB,IAA8C,CACrF,KAAK,aAAa,EAElB,IAAM,EAAO,IAAI,EAAa,KAAM,EAAQ,CAAO,EAInD,OAFC,KAAK,mBAAqB,KAAK,YAAA,CAAa,MAAM,IAAI,CAAI,EAEpD,CACT,EAEA,QAAmB,EAAqC,IAA0C,CAChG,KAAK,aAAa,EAElB,IAAM,EAAO,IAAI,EAAW,KAAM,EAAU,CAAO,EAKnD,OAHC,KAAK,mBAAqB,KAAK,YAAA,CAAa,MAAM,IAAI,CAAI,EAC3D,EAAK,IAAI,EAEF,CACT,EAEA,YAAwB,GAAyB,CAC/C,KAAK,aAAa,EAElB,IAAM,EAAQ,IAAI,EAAU,KAAM,CAAI,EAQtC,OAFA,KAAK,YAAY,MAAM,IAAI,CAAK,EAEzB,CACT,EAEA,MAAqB,IACnB,KAAK,aAAa,EAEX,KAAK,UAAU,CAAE,GAG1B,QAAuB,IACrB,KAAK,aAAa,EAEX,KAAK,aAAa,IAAA,GAAW,CAAE,GAGxC,SAAgB,CACV,KAAK,aAET,KAAK,WAAa,GAClB,KAAK,UAAU,QAAQ,EACzB,CAGA,cAAqB,CACnB,GAAI,KAAK,WAAY,MAAM,IAAI,EAA2B,uCAAuC,CACnG,CAEA,MAAM,EAAwB,CAC5B,IAAM,EAAW,KAAK,eAElB,GAAU,aAAe,IAAA,IAE7B,EAAS,WAAW,IAAI,CAAI,CAC9B,CAEA,kBAAkB,EAA8B,CAC9C,IAAK,IAAM,KAAc,EAAS,aAAc,EAAW,WAAW,OAAO,CAAQ,EACrF,EAAS,aAAa,MAAM,CAC9B,CAEA,QAAW,EAAwB,EAAgB,CAKjD,OAAO,KAAK,YAAY,EAAU,EAAI,EAAS,aAAa,OAAS,CAAC,CACxE,CAEA,cAAiB,EAAwB,EAAgB,CACvD,OAAO,KAAK,YAAY,EAAU,EAAI,EAAI,CAC5C,CAEA,gBAAmB,EAAkB,EAAgB,CACnD,IAAM,EAAW,KAAK,kBAEtB,KAAK,kBAAoB,EAEzB,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,KAAK,kBAAoB,CAC3B,CACF,CAEA,aAAgB,EAAoC,EAAgB,CAClE,IAAM,EAAW,KAAK,eAEtB,KAAK,eAAiB,EAEtB,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,KAAK,eAAiB,CACxB,CACF,CAEA,UAAa,EAAkB,EAAgB,CAC7C,IAAM,EAAsB,KAAK,kBAC3B,EAAgB,KAAK,YAE3B,KAAK,kBAAoB,IAAA,GACzB,KAAK,YAAc,EAEnB,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,KAAK,kBAAoB,EACzB,KAAK,YAAc,CACrB,CACF,CAEA,QAAQ,EAA0B,CAChC,KAAK,QAAQ,IAAI,CAAM,EAEnB,KAAK,aAAe,GAAG,KAAK,MAAM,CACxC,CAEA,gBAAgB,EAA4B,CAC1C,KAAK,UAAU,IAAI,CAAQ,EAEvB,KAAK,aAAe,GAAG,KAAK,MAAM,CACxC,CAEA,UAAa,EAAgB,CAC3B,KAAK,aAEL,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,KAAK,aAED,KAAK,aAAe,GAAG,KAAK,MAAM,CACxC,CACF,CAEA,KAAK,EAA8C,CACjD,GAAI,CACF,KAAK,WAAW,CAAK,CACvB,OAAS,EAAO,CACd,KAAK,OAAO,EAAO,CAAE,KAAM,WAAY,KAAM,EAAM,IAAK,CAAC,CAC3D,CACF,CAEA,OAAO,EAAgB,EAAqC,CAC1D,GAAI,CACF,KAAK,QAAQ,EAAO,CAAO,CAC7B,OAAS,EAAe,CACtB,mBAAqB,CACnB,MAAM,CACR,CAAC,CACH,CACF,CAEA,YAAuB,EAAwB,EAAa,EAA2B,CACrF,IAAM,EAAmB,KAAK,eACxB,EAAe,IAAI,IAEzB,EAAS,WAAa,EACtB,KAAK,eAAiB,EAEtB,GAAI,CACF,IAAM,EAAS,EAAG,EAIlB,OAFA,KAAK,mBAAmB,EAAU,CAAY,EAEvC,CACT,OAAS,EAAO,CAGd,MAFI,GAAe,KAAK,mBAAmB,EAAU,CAAY,EAE3D,CACR,QAAU,CACR,EAAS,WAAa,IAAA,GACtB,KAAK,eAAiB,CACxB,CACF,CAEA,mBAA2B,EAAwB,EAA6B,CAC9E,IAAK,IAAM,KAAc,EAAS,aAC3B,EAAK,IAAI,CAAU,GAAG,EAAW,WAAW,OAAO,CAAQ,EAGlE,IAAK,IAAM,KAAc,EAClB,EAAS,aAAa,IAAI,CAAU,GAAG,EAAW,WAAW,IAAI,CAAQ,EAGhF,EAAS,aAAa,MAAM,EAC5B,IAAK,IAAM,KAAc,EAAM,EAAS,aAAa,IAAI,CAAU,CACrE,CAEA,OAAsB,CACpB,GAAI,KAAK,SAAU,OAEnB,KAAK,SAAW,GAEhB,IAAI,EAAa,EAEjB,GAAI,CACF,KAAO,KAAK,QAAQ,KAAO,GAAK,KAAK,UAAU,KAAO,GAAG,CACvD,GAAI,EAAE,EAAa,EACjB,MAAM,IAAI,EAAwB,6BAA6B,EAAqB,aAAa,EAGnG,IAAM,EAAU,CAAC,GAAG,KAAK,OAAO,EAC1B,EAAY,CAAC,GAAG,KAAK,SAAS,EAEpC,KAAK,QAAQ,MAAM,EACnB,KAAK,UAAU,MAAM,EAErB,IAAK,IAAM,KAAU,EAAS,EAAO,IAAI,EAEzC,IAAK,IAAM,KAAY,EACrB,GAAI,CACF,EAAS,CACX,OAAS,EAAO,CACd,KAAK,OAAO,EAAO,CAAE,KAAM,UAAW,CAAC,CACzC,CAEJ,CACF,QAAU,CACR,KAAK,SAAW,EAClB,CACF,CACF,EAEa,EAAiB,GAAiD,CAC7E,GAAI,OAAO,GAAU,WAAY,GAAkB,EAAE,KAAY,GAAQ,MAAO,GAEhF,IAAM,EAAY,EAElB,OAAO,OAAO,EAAU,MAAS,YAAc,OAAO,EAAU,WAAc,UAChF,EClkBa,EACV,IAEC,EACA,EACA,IACoB,CACpB,IAAM,EAAQ,EAAQ,OAA0B,CAAE,OAAQ,SAAU,EAAG,CAAE,KAAM,GAAS,IAAK,CAAC,EACxF,EAAc,EAAQ,OAAO,CAAC,EAChC,EACA,EAAW,GAET,MAAkB,CACtB,EAAiB,MACjB,GAAQ,MAAM,EAEd,IAAM,EAAU,EAAM,KAAK,EACrB,EACJ,EAAQ,SAAW,UAAY,EAAQ,MAAQ,aAAc,EAAU,EAAQ,SAAW,IAAA,GACxF,EAEJ,GAAI,CACF,EAAQ,EAAO,CACjB,OAAS,EAAO,CACd,EAAM,MAAQ,IAAa,IAAA,GAAY,CAAE,QAAO,OAAQ,OAAQ,EAAI,CAAE,QAAO,WAAU,OAAQ,OAAQ,EAEvG,MACF,CAEA,IAAM,EAAO,IAAI,gBAEjB,EAAS,EACT,EAAM,MAAQ,IAAa,IAAA,GAAY,CAAE,OAAQ,SAAU,EAAI,CAAE,WAAU,OAAQ,SAAU,EAE7F,IAAI,EAEJ,GAAI,CACF,EAAU,QAAQ,QAAQ,EAAO,EAAO,CAAE,OAAQ,EAAK,MAAO,CAAC,CAAC,CAClE,OAAS,EAAO,CACd,EAAU,QAAQ,OAAO,CAAK,CAChC,CAEA,EAAa,KACV,GAAU,CACL,CAAC,GAAY,CAAC,EAAK,OAAO,UAAS,EAAM,MAAQ,CAAE,OAAQ,UAAW,OAAM,EAClF,EACC,GAAmB,CACd,CAAC,GAAY,CAAC,EAAK,OAAO,UAC5B,EAAM,MAAQ,IAAa,IAAA,GAAY,CAAE,QAAO,OAAQ,OAAQ,EAAI,CAAE,QAAO,WAAU,OAAQ,OAAQ,EAE3G,CACF,CACF,EAEM,EAAO,EAAQ,YAEjB,EAAI,MAES,GAAQ,MAAM,GAE7B,CAAE,KAAM,GAAS,IAAK,CACxB,EAEA,EAAK,eAAe,iBAClB,YACM,CACJ,EAAW,EACb,EACA,CAAE,KAAM,EAAK,CACf,EAEA,IAAM,EAA4B,CAChC,IAAI,gBAAiB,CACnB,OAAO,EAAK,cACd,EACA,YAAe,EAAK,QAAQ,EAC5B,IAAI,UAAW,CACb,OAAO,CACT,EACA,IAAI,MAAO,CACT,OAAO,EAAM,IACf,EACA,SAAY,EAAM,KAAK,EACvB,WAAc,CACR,IAEJ,EAAY,MAAQ,EAAY,KAAK,EAAI,EAC3C,EACA,UAAY,GAAa,EAAM,UAAU,CAAQ,EACjD,CAAC,OAAO,UAAW,CACjB,KAAK,QAAQ,CACf,EACA,IAAI,OAAQ,CACV,OAAO,EAAM,KACf,CACF,EAIA,OAFA,OAAO,eAAe,EAAU,EAAU,CAAE,MAAO,EAAK,CAAC,EAElD,CACT,EC7GW,EACV,IAEC,EACA,EACA,IACiB,CACjB,IAAM,EAAO,OAAO,GAAW,WAAa,MAAe,EAAO,MAC5D,EAAS,GAAS,QAAU,OAAO,GACrC,EAAU,GACV,EAIA,EAAmB,GAEjB,EAAS,EAAQ,WACf,CACJ,IAAM,EAAQ,EAAK,EAEnB,GAAI,EAAS,CACX,EAAU,GACV,EAAW,EAEP,GAAS,YACX,EAAS,EAAO,IAAA,EAAS,EACrB,GAAS,OAAM,EAAmB,KAGxC,MACF,CAEA,GAAI,EAAO,EAAe,CAAK,EAAG,OAElC,IAAM,EAAW,EAEjB,EAAW,EACX,EAAS,EAAO,CAAQ,EAEpB,GAAS,MAAM,EAAO,QAAQ,CACpC,EACA,CAAE,KAAM,GAAS,IAAK,CACxB,EAIA,OAFI,GAAkB,EAAO,QAAQ,EAE9B,CACT,ECvBW,EAAgB,GAAoC,CAC/D,IAAM,EAAU,IAAI,EAAgB,CAAO,EACrC,EAAW,EAAe,CAAO,EAEvC,MAAO,CACL,MAAO,EAAQ,MACf,SAAU,EAAQ,SAClB,YAAa,EAAQ,YACrB,YAAe,EAAQ,QAAQ,EAC/B,IAAI,UAAW,CACb,OAAO,EAAQ,QACjB,EACA,OAAQ,EAAQ,OAChB,WACA,OAAQ,EAAQ,OAChB,QAAS,EAAQ,QACjB,MAAO,EAAY,CAAO,CAC5B,CACF,EAOa,EAAgB,EAAa,EC/B7B,EAAS,EAAc,OACvB,EAAW,EAAc,SACzB,EAAS,EAAc,OACvB,EAAQ,EAAc,MACtB,EAAc,EAAc,YAC5B,EAAU,EAAc,QACxB,EAAQ,EAAc,MACtB,EAAW,EAAc"}
|
package/dist/ripple.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{},n=class extends e{},r=class extends e{},i=class extends e{},a=Symbol.for(`@vielzeug/ripple/reactive`),o=100,s=Symbol(`ripple.unset`),c=class{[a]=!0;dependents=new Set;name;runtime;constructor(e,t){this.runtime=e,this.name=t}subscribe(e){this.runtime.assertActive(),this.peek();let t={dependencies:new Set,onDependencyChanged:()=>this.runtime.enqueueListener(e)};return this.dependents.add(t),()=>this.dependents.delete(t)}notify(){for(let e of[...this.dependents])e.onDependencyChanged()}},l=class extends c{current;equals;constructor(e,t,n){super(e,n?.name),this.current=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.current}set value(e){if(this.runtime.assertActive(),this.equals(this.current,e))return;let t=this.current;this.current=e,this.runtime.emit({kind:`write`,name:this.name,next:e,previous:t}),this.runtime.propagate(()=>this.notify())}peek(){return this.current}update(e){this.value=e(this.current)}},u=class extends c{dependencies=new Set;computing=!1;disposed=!1;dirty=!0;current=s;derive;equals;constructor(e,t,n){super(e,n?.name),this.derive=t,this.equals=n?.equals??Object.is}get value(){return this.
|
|
1
|
+
var e=class extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}},t=class extends e{},n=class extends e{},r=class extends e{},i=class extends e{},a=Symbol.for(`@vielzeug/ripple/reactive`),o=100,s=Symbol(`ripple.unset`),c=class{[a]=!0;dependents=new Set;name;runtime;constructor(e,t){this.runtime=e,this.name=t}subscribe(e){this.runtime.assertActive(),this.peek();let t={dependencies:new Set,onDependencyChanged:()=>this.runtime.enqueueListener(e)};return this.dependents.add(t),()=>this.dependents.delete(t)}notify(){for(let e of[...this.dependents])e.onDependencyChanged()}},l=class extends c{current;equals;constructor(e,t,n){super(e,n?.name),this.current=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.current}set value(e){if(this.runtime.assertActive(),this.equals(this.current,e))return;let t=this.current;this.current=e,this.runtime.emit({kind:`write`,name:this.name,next:e,previous:t}),this.runtime.propagate(()=>this.notify())}peek(){return this.current}update(e){this.value=e(this.current)}},u=class extends c{dependencies=new Set;computing=!1;disposed=!1;dirty=!0;current=s;derive;equals;constructor(e,t,n){super(e,n?.name),this.derive=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.refresh(),this.current}peek(){return this.refresh(),this.current}onDependencyChanged(){this.disposed||(this.dirty||=!0,this.dependents.size>0&&this.refresh()&&this.notify())}dispose(){this.disposed||(this.disposed=!0,this.runtime.clearDependencies(this),this.dependents.clear())}refresh(){if(!this.dirty||this.disposed)return!1;if(this.computing)throw new t(`computed cycle detected${this.name===void 0?``:` "${this.name}"`}`);this.computing=!0,this.runtime.emit({kind:`compute`,name:this.name});try{let e=this.runtime.collect(this,this.derive),t=this.current===s||!this.equals(this.current,e);return this.current=e,this.dirty=!1,t}finally{this.computing=!1}}},d=class{disposalController=new AbortController;owned=new Set;name;isDisposed=!1;runtime;constructor(e,t){this.runtime=e,this.name=t}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}run(e){if(this.isDisposed)throw new r(`Cannot run a disposed scope.`);return this.runtime.withScope(this,e)}dispose(){if(!this.isDisposed){this.isDisposed=!0;for(let e of[...this.owned].reverse())e.dispose();this.owned.clear(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.name,node:`scope`})}}[Symbol.dispose](){this.dispose()}},f=class{dependencies=new Set;disposalController=new AbortController;cleanup;isDisposed=!1;owner;scheduled=!1;callback;options;runtime;constructor(e,t,n){this.runtime=e,this.callback=t,this.options=n}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}onDependencyChanged(){if(!this.isDisposed){if(this.options?.scheduler===`microtask`){if(this.scheduled)return;this.scheduled=!0,queueMicrotask(()=>{this.scheduled=!1,this.isDisposed||this.runtime.enqueue(this)});return}this.runtime.enqueue(this)}}run(){if(this.isDisposed)return;this.owner?.dispose(),this.owner=void 0,this.runCleanup(),this.runtime.emit({kind:`effect`,name:this.options?.name});let e=new d(this.runtime);try{let t=this.runtime.withEffectScope(e,()=>this.runtime.collectEffect(this,this.callback));this.owner=e,this.cleanup=typeof t==`function`?t:void 0}catch(t){e.dispose(),this.runtime.report(t,{kind:`effect`,name:this.options?.name})}}dispose(){this.isDisposed||(this.isDisposed=!0,this.owner?.dispose(),this.owner=void 0,this.runtime.clearDependencies(this),this.runCleanup(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.options?.name,node:`effect`}))}[Symbol.dispose](){this.dispose()}runCleanup(){let e=this.cleanup;if(this.cleanup=void 0,e!==void 0)try{e()}catch(e){this.runtime.report(e,{kind:`cleanup`,name:this.options?.name})}}},p=class{activeEffectScope;activeObserver;activeScope;isDisposed=!1;flushDepth=0;flushing=!1;pending=new Set;listeners=new Set;rootScope;observer;onError;constructor(e){this.observer=e?.observer,this.onError=e?.onError??(e=>{queueMicrotask(()=>{throw e})}),this.rootScope=new d(this,`runtime`),this.activeScope=this.rootScope}get disposed(){return this.isDisposed}signal=(e,t)=>(this.assertActive(),new l(this,e,t));computed=(e,t)=>{this.assertActive();let n=new u(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n};effect=(e,t)=>{this.assertActive();let n=new f(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n.run(),n};createScope=e=>{this.assertActive();let t=new d(this,e);return this.activeScope.owned.add(t),t};batch=e=>(this.assertActive(),this.propagate(e));untrack=e=>(this.assertActive(),this.withObserver(void 0,e));dispose(){this.isDisposed||(this.isDisposed=!0,this.rootScope.dispose())}assertActive(){if(this.isDisposed)throw new n(`Cannot use a disposed Ripple runtime.`)}track(e){let t=this.activeObserver;t?.collecting!==void 0&&t.collecting.add(e)}clearDependencies(e){for(let t of e.dependencies)t.dependents.delete(e);e.dependencies.clear()}collect(e,t){return this.collectWith(e,t,e.dependencies.size===0)}collectEffect(e,t){return this.collectWith(e,t,!0)}withEffectScope(e,t){let n=this.activeEffectScope;this.activeEffectScope=e;try{return t()}finally{this.activeEffectScope=n}}withObserver(e,t){let n=this.activeObserver;this.activeObserver=e;try{return t()}finally{this.activeObserver=n}}withScope(e,t){let n=this.activeEffectScope,r=this.activeScope;this.activeEffectScope=void 0,this.activeScope=e;try{return t()}finally{this.activeEffectScope=n,this.activeScope=r}}enqueue(e){this.pending.add(e),this.flushDepth===0&&this.flush()}enqueueListener(e){this.listeners.add(e),this.flushDepth===0&&this.flush()}propagate(e){this.flushDepth++;try{return e()}finally{this.flushDepth--,this.flushDepth===0&&this.flush()}}emit(e){try{this.observer?.(e)}catch(t){this.report(t,{kind:`observer`,name:e.name})}}report(e,t){try{this.onError(e,t)}catch(e){queueMicrotask(()=>{throw e})}}collectWith(e,t,n){let r=this.activeObserver,i=new Set;e.collecting=i,this.activeObserver=e;try{let n=t();return this.commitDependencies(e,i),n}catch(t){throw n&&this.commitDependencies(e,i),t}finally{e.collecting=void 0,this.activeObserver=r}}commitDependencies(e,t){for(let n of e.dependencies)t.has(n)||n.dependents.delete(e);for(let n of t)e.dependencies.has(n)||n.dependents.add(e);e.dependencies.clear();for(let n of t)e.dependencies.add(n)}flush(){if(this.flushing)return;this.flushing=!0;let e=0;try{for(;this.pending.size>0||this.listeners.size>0;){if(++e>o)throw new i(`infinite reactive flush (>${o} iterations)`);let t=[...this.pending],n=[...this.listeners];this.pending.clear(),this.listeners.clear();for(let e of t)e.run();for(let e of n)try{e()}catch(e){this.report(e,{kind:`listener`})}}}finally{this.flushing=!1}}},m=e=>{if(typeof e!=`object`||!e||!(a in e))return!1;let t=e;return typeof t.peek==`function`&&typeof t.subscribe==`function`},h=e=>(t,n,r)=>{let i=e.signal({status:`pending`},{name:r?.name}),o=e.signal(0),s,c=!1,l=()=>{o.value,s?.abort();let e=i.peek(),r=e.status===`success`?e.value:`previous`in e?e.previous:void 0,a;try{a=t()}catch(e){i.value=r===void 0?{error:e,status:`error`}:{error:e,previous:r,status:`error`};return}let l=new AbortController;s=l,i.value=r===void 0?{status:`pending`}:{previous:r,status:`pending`};let u;try{u=Promise.resolve(n(a,{signal:l.signal}))}catch(e){u=Promise.reject(e)}u.then(e=>{!c&&!l.signal.aborted&&(i.value={status:`success`,value:e})},e=>{!c&&!l.signal.aborted&&(i.value=r===void 0?{error:e,status:`error`}:{error:e,previous:r,status:`error`})})},u=e.effect(()=>(l(),()=>s?.abort()),{name:r?.name});u.disposalSignal.addEventListener(`abort`,()=>{c=!0},{once:!0});let d={get disposalSignal(){return u.disposalSignal},dispose:()=>u.dispose(),get disposed(){return c},get name(){return i.name},peek:()=>i.peek(),reload:()=>{c||(o.value=o.peek()+1)},subscribe:e=>i.subscribe(e),[Symbol.dispose](){this.dispose()},get value(){return i.value}};return Object.defineProperty(d,a,{value:!0}),d},g=e=>(t,n,r)=>{let i=typeof t==`function`?t:()=>t.value,a=r?.equals??Object.is,o=!0,s,c=!1,l=e.effect(()=>{let e=i();if(o){o=!1,s=e,r?.immediate&&(n(e,void 0),r?.once&&(c=!0));return}if(a(s,e))return;let t=s;s=e,n(e,t),r?.once&&l.dispose()},{name:r?.name});return c&&l.dispose(),l},_=e=>{let t=new p(e),n=h(t);return{batch:t.batch,computed:t.computed,createScope:t.createScope,dispose:()=>t.dispose(),get disposed(){return t.disposed},effect:t.effect,resource:n,signal:t.signal,untrack:t.untrack,watch:g(t)}},v=_(),y=v.signal,b=v.computed,x=v.effect,S=v.batch,C=v.createScope,w=v.untrack,T=v.watch,E=v.resource;export{t as RippleComputedCycleError,n as RippleDisposedRuntimeError,r as RippleDisposedScopeError,e as RippleError,i as RippleInfiniteLoopError,S as batch,b as computed,_ as createRipple,C as createScope,x as effect,m as isReactive,E as resource,y as signal,w as untrack,T as watch};
|
|
2
2
|
//# sourceMappingURL=ripple.js.map
|
package/dist/ripple.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ripple.js","names":[],"sources":["../src/errors.ts","../src/runtime.ts","../src/_async.ts","../src/_watch.ts","../src/_default.ts","../src/index.ts"],"sourcesContent":["export class RippleError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class RippleComputedCycleError extends RippleError {}\nexport class RippleDisposedRuntimeError extends RippleError {}\nexport class RippleDisposedScopeError extends RippleError {}\nexport class RippleInfiniteLoopError extends RippleError {}\n","import {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleInfiniteLoopError,\n} from './errors';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n ReactiveErrorContext,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nexport const REACTIVE = Symbol.for('@vielzeug/ripple/reactive');\nconst MAX_FLUSH_ITERATIONS = 100;\nconst UNSET = Symbol('ripple.unset');\n\ntype Dependency = ReactiveNode<unknown>;\n\ntype ObserverNode = {\n collecting?: Set<Dependency>;\n readonly dependencies: Set<Dependency>;\n onDependencyChanged(): void;\n};\n\ntype Owned = {\n dispose(): void;\n};\n\nabstract class ReactiveNode<T> {\n readonly [REACTIVE] = true;\n readonly dependents = new Set<ObserverNode>();\n readonly name: string | undefined;\n protected readonly runtime: ReactiveRuntime;\n\n protected constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n abstract peek(): T;\n abstract get value(): T;\n\n subscribe(listener: () => void): Unsubscribe {\n this.runtime.assertActive();\n this.peek();\n\n const observer: ObserverNode = {\n dependencies: new Set(),\n onDependencyChanged: () => this.runtime.enqueueListener(listener),\n };\n\n this.dependents.add(observer);\n\n return () => this.dependents.delete(observer);\n }\n\n protected notify(): void {\n for (const dependent of [...this.dependents]) dependent.onDependencyChanged();\n }\n}\n\nclass SignalNode<T> extends ReactiveNode<T> implements Signal<T> {\n private current: T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, initial: T, options?: SignalOptions<T>) {\n super(runtime, options?.name);\n this.current = initial;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.runtime.track(this);\n\n return this.current;\n }\n\n set value(next: T) {\n this.runtime.assertActive();\n\n if (this.equals(this.current, next)) return;\n\n const previous = this.current;\n\n this.current = next;\n this.runtime.emit({ kind: 'write', name: this.name, next, previous });\n this.runtime.propagate(() => this.notify());\n }\n\n peek(): T {\n return this.current;\n }\n\n update(updater: (prev: T) => T): void {\n this.value = updater(this.current);\n }\n}\n\nclass ComputedNode<T> extends ReactiveNode<T> implements ObserverNode, Owned {\n readonly dependencies = new Set<Dependency>();\n private computing = false;\n private disposed = false;\n private dirty = true;\n private current: T | typeof UNSET = UNSET;\n private readonly derive: () => T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, derive: () => T, options?: ComputedOptions<T>) {\n super(runtime, options?.name);\n this.derive = derive;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.refresh();\n this.runtime.track(this);\n\n return this.current as T;\n }\n\n peek(): T {\n this.refresh();\n\n return this.current as T;\n }\n\n onDependencyChanged(): void {\n if (this.disposed) return;\n\n if (!this.dirty) this.dirty = true;\n\n if (this.dependents.size > 0 && this.refresh()) this.notify();\n }\n\n dispose(): void {\n if (this.disposed) return;\n\n this.disposed = true;\n this.runtime.clearDependencies(this);\n this.dependents.clear();\n }\n\n private refresh(): boolean {\n if (!this.dirty || this.disposed) return false;\n\n if (this.computing) {\n const label = this.name === undefined ? '' : ` \"${this.name}\"`;\n\n throw new RippleComputedCycleError(`computed cycle detected${label}`);\n }\n\n this.computing = true;\n this.runtime.emit({ kind: 'compute', name: this.name });\n\n try {\n const next = this.runtime.collect(this, this.derive);\n const changed = this.current === UNSET || !this.equals(this.current as T, next);\n\n this.current = next;\n this.dirty = false;\n\n return changed;\n } finally {\n this.computing = false;\n }\n }\n}\n\nclass ScopeNode implements Scope {\n readonly disposalController = new AbortController();\n readonly owned = new Set<Owned>();\n readonly name: string | undefined;\n private isDisposed = false;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n run<T>(fn: () => T): T {\n if (this.isDisposed) throw new RippleDisposedScopeError('Cannot run a disposed scope.');\n\n return this.runtime.withScope(this, fn);\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n for (const owned of [...this.owned].reverse()) owned.dispose();\n this.owned.clear();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.name, node: 'scope' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nclass EffectNode implements ObserverNode, EffectHandle {\n readonly dependencies = new Set<Dependency>();\n readonly disposalController = new AbortController();\n private cleanup: Cleanup | undefined;\n private isDisposed = false;\n private owner: ScopeNode | undefined;\n private scheduled = false;\n private readonly callback: () => Cleanup | undefined;\n private readonly options: EffectOptions | undefined;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, callback: () => Cleanup | undefined, options?: EffectOptions) {\n this.runtime = runtime;\n this.callback = callback;\n this.options = options;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n onDependencyChanged(): void {\n if (this.isDisposed) return;\n\n if (this.options?.scheduler === 'microtask') {\n if (this.scheduled) return;\n\n this.scheduled = true;\n queueMicrotask(() => {\n this.scheduled = false;\n\n if (!this.isDisposed) this.runtime.enqueue(this);\n });\n\n return;\n }\n\n this.runtime.enqueue(this);\n }\n\n run(): void {\n if (this.isDisposed) return;\n\n this.owner?.dispose();\n this.owner = undefined;\n this.runCleanup();\n this.runtime.emit({ kind: 'effect', name: this.options?.name });\n\n const owner = new ScopeNode(this.runtime);\n\n try {\n const cleanup = this.runtime.withEffectScope(owner, () => this.runtime.collectEffect(this, this.callback));\n\n this.owner = owner;\n this.cleanup = typeof cleanup === 'function' ? cleanup : undefined;\n } catch (error) {\n owner.dispose();\n this.runtime.report(error, { kind: 'effect', name: this.options?.name });\n }\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.owner?.dispose();\n this.owner = undefined;\n this.runtime.clearDependencies(this);\n this.runCleanup();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.options?.name, node: 'effect' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n private runCleanup(): void {\n const cleanup = this.cleanup;\n\n this.cleanup = undefined;\n\n if (cleanup === undefined) return;\n\n try {\n cleanup();\n } catch (error) {\n this.runtime.report(error, { kind: 'cleanup', name: this.options?.name });\n }\n }\n}\n\n/**\n * A runtime owns reactive graph state and lifetime. Separate instances isolate\n * applications and SSR requests without process-wide mutable hooks.\n */\nexport class ReactiveRuntime {\n private activeEffectScope: ScopeNode | undefined;\n private activeObserver: ObserverNode | undefined;\n private activeScope: ScopeNode;\n private isDisposed = false;\n private flushDepth = 0;\n private flushing = false;\n private readonly pending = new Set<EffectNode>();\n private readonly listeners = new Set<() => void>();\n private readonly rootScope: ScopeNode;\n private readonly observer: ReactiveObserver | undefined;\n private readonly onError: (error: unknown, context: ReactiveErrorContext) => void;\n\n constructor(options?: RippleOptions) {\n this.observer = options?.observer;\n this.onError =\n options?.onError ??\n ((error) => {\n queueMicrotask(() => {\n throw error;\n });\n });\n this.rootScope = new ScopeNode(this, 'runtime');\n this.activeScope = this.rootScope;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n readonly signal = <T>(initial: T, options?: SignalOptions<T>): Signal<T> => {\n this.assertActive();\n\n return new SignalNode(this, initial, options);\n };\n\n readonly computed = <T>(derive: () => T, options?: ComputedOptions<T>): Readable<T> => {\n this.assertActive();\n\n const node = new ComputedNode(this, derive, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n\n return node;\n };\n\n readonly effect = (callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle => {\n this.assertActive();\n\n const node = new EffectNode(this, callback, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n node.run();\n\n return node;\n };\n\n readonly createScope = (name?: string): Scope => {\n this.assertActive();\n\n const scope = new ScopeNode(this, name);\n\n // Scopes model explicit, caller-owned lifetimes. Unlike effects/computeds created during an\n // effect run, they deliberately attach to the enclosing scope rather than the per-run owner:\n // keyed DOM directives retain item scopes across reconciliation runs and dispose them only\n // when the item itself leaves the collection.\n this.activeScope.owned.add(scope);\n\n return scope;\n };\n\n readonly batch = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.propagate(fn);\n };\n\n readonly untrack = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.withObserver(undefined, fn);\n };\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.rootScope.dispose();\n }\n\n /** Internal node guard: disposed runtimes allow inert reads but reject graph work and mutation. */\n assertActive(): void {\n if (this.isDisposed) throw new RippleDisposedRuntimeError('Cannot use a disposed Ripple runtime.');\n }\n\n track(node: Dependency): void {\n const observer = this.activeObserver;\n\n if (observer?.collecting === undefined) return;\n\n observer.collecting.add(node);\n }\n\n clearDependencies(observer: ObserverNode): void {\n for (const dependency of observer.dependencies) dependency.dependents.delete(observer);\n observer.dependencies.clear();\n }\n\n collect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, false);\n }\n\n collectEffect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, true);\n }\n\n withEffectScope<T>(scope: ScopeNode, fn: () => T): T {\n const previous = this.activeEffectScope;\n\n this.activeEffectScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previous;\n }\n }\n\n withObserver<T>(observer: ObserverNode | undefined, fn: () => T): T {\n const previous = this.activeObserver;\n\n this.activeObserver = observer;\n\n try {\n return fn();\n } finally {\n this.activeObserver = previous;\n }\n }\n\n withScope<T>(scope: ScopeNode, fn: () => T): T {\n const previousEffectScope = this.activeEffectScope;\n const previousScope = this.activeScope;\n\n this.activeEffectScope = undefined;\n this.activeScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previousEffectScope;\n this.activeScope = previousScope;\n }\n }\n\n enqueue(effect: EffectNode): void {\n this.pending.add(effect);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n enqueueListener(listener: () => void): void {\n this.listeners.add(listener);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n propagate<T>(fn: () => T): T {\n this.flushDepth++;\n\n try {\n return fn();\n } finally {\n this.flushDepth--;\n\n if (this.flushDepth === 0) this.flush();\n }\n }\n\n emit(event: Parameters<ReactiveObserver>[0]): void {\n try {\n this.observer?.(event);\n } catch (error) {\n this.report(error, { kind: 'observer', name: event.name });\n }\n }\n\n report(error: unknown, context: ReactiveErrorContext): void {\n try {\n this.onError(error, context);\n } catch (reporterError) {\n queueMicrotask(() => {\n throw reporterError;\n });\n }\n }\n\n private collectWith<T>(observer: ObserverNode, fn: () => T, commitOnError: boolean): T {\n const previousObserver = this.activeObserver;\n const dependencies = new Set<Dependency>();\n\n observer.collecting = dependencies;\n this.activeObserver = observer;\n\n try {\n const result = fn();\n\n this.commitDependencies(observer, dependencies);\n\n return result;\n } catch (error) {\n if (commitOnError) this.commitDependencies(observer, dependencies);\n\n throw error;\n } finally {\n observer.collecting = undefined;\n this.activeObserver = previousObserver;\n }\n }\n\n private commitDependencies(observer: ObserverNode, next: Set<Dependency>): void {\n for (const dependency of observer.dependencies) {\n if (!next.has(dependency)) dependency.dependents.delete(observer);\n }\n\n for (const dependency of next) {\n if (!observer.dependencies.has(dependency)) dependency.dependents.add(observer);\n }\n\n observer.dependencies.clear();\n for (const dependency of next) observer.dependencies.add(dependency);\n }\n\n private flush(): void {\n if (this.flushing) return;\n\n this.flushing = true;\n\n let iterations = 0;\n\n try {\n while (this.pending.size > 0 || this.listeners.size > 0) {\n if (++iterations > MAX_FLUSH_ITERATIONS) {\n throw new RippleInfiniteLoopError(`infinite reactive flush (>${MAX_FLUSH_ITERATIONS} iterations)`);\n }\n\n const effects = [...this.pending];\n const listeners = [...this.listeners];\n\n this.pending.clear();\n this.listeners.clear();\n\n for (const effect of effects) effect.run();\n\n for (const listener of listeners) {\n try {\n listener();\n } catch (error) {\n this.report(error, { kind: 'listener' });\n }\n }\n }\n } finally {\n this.flushing = false;\n }\n }\n}\n\nexport const isReactive = <T>(value: T | Readable<T>): value is Readable<T> => {\n if (typeof value !== 'object' || value === null || !(REACTIVE in value)) return false;\n\n const candidate = value as { peek?: unknown; subscribe?: unknown };\n\n return typeof candidate.peek === 'function' && typeof candidate.subscribe === 'function';\n};\n","import { REACTIVE } from './runtime';\nimport type { Disposable, EffectHandle, Readable, Signal } from './types';\n\nexport type AsyncState<T> =\n | { readonly previous?: T; readonly status: 'pending' }\n | { readonly status: 'success'; readonly value: T }\n | { readonly error: unknown; readonly previous?: T; readonly status: 'error' };\n\nexport interface Resource<T> extends Readable<AsyncState<T>>, Disposable {\n reload(): void;\n}\n\nexport type ResourceOptions = {\n name?: string;\n};\n\ntype AsyncRuntime = {\n effect(callback: () => undefined | (() => void), options?: { name?: string }): EffectHandle;\n signal<T>(initial: T, options?: { name?: string }): Signal<T>;\n};\n\n/** Resource only depends on primitive runtime methods; graph binding stays private. */\nexport const createResource =\n (runtime: AsyncRuntime) =>\n <Source, Value>(\n source: () => Source,\n loader: (source: Source, context: { readonly signal: AbortSignal }) => Promise<Value>,\n options?: ResourceOptions,\n ): Resource<Value> => {\n const state = runtime.signal<AsyncState<Value>>({ status: 'pending' }, { name: options?.name });\n const reloadEpoch = runtime.signal(0);\n let active: AbortController | undefined;\n let disposed = false;\n\n const run = (): void => {\n void reloadEpoch.value;\n active?.abort();\n\n const current = state.peek();\n const previous =\n current.status === 'success' ? current.value : 'previous' in current ? current.previous : undefined;\n let input: Source;\n\n try {\n input = source();\n } catch (error) {\n state.value = previous === undefined ? { error, status: 'error' } : { error, previous, status: 'error' };\n\n return;\n }\n\n const next = new AbortController();\n\n active = next;\n state.value = previous === undefined ? { status: 'pending' } : { previous, status: 'pending' };\n\n let request: Promise<Value>;\n\n try {\n request = Promise.resolve(loader(input, { signal: next.signal }));\n } catch (error) {\n request = Promise.reject(error);\n }\n\n void request.then(\n (value) => {\n if (!disposed && !next.signal.aborted) state.value = { status: 'success', value };\n },\n (error: unknown) => {\n if (!disposed && !next.signal.aborted) {\n state.value = previous === undefined ? { error, status: 'error' } : { error, previous, status: 'error' };\n }\n },\n );\n };\n\n const stop = runtime.effect(\n () => {\n run();\n\n return () => active?.abort();\n },\n { name: options?.name },\n );\n\n stop.disposalSignal.addEventListener(\n 'abort',\n () => {\n disposed = true;\n },\n { once: true },\n );\n\n const resource: Resource<Value> = {\n get disposalSignal() {\n return stop.disposalSignal;\n },\n dispose: () => stop.dispose(),\n get disposed() {\n return disposed;\n },\n get name() {\n return state.name;\n },\n peek: () => state.peek(),\n reload: () => {\n if (disposed) return;\n\n reloadEpoch.value = reloadEpoch.peek() + 1;\n },\n subscribe: (listener) => state.subscribe(listener),\n [Symbol.dispose]() {\n this.dispose();\n },\n get value() {\n return state.value;\n },\n };\n\n Object.defineProperty(resource, REACTIVE, { value: true });\n\n return resource;\n };\n","import type { EffectHandle, Equality, Readable } from './types';\n\nexport type WatchOptions<T> = {\n equals?: Equality<T>;\n immediate?: boolean;\n name?: string;\n once?: boolean;\n};\n\ntype WatchRuntime = {\n effect(callback: () => undefined | (() => void), options?: { name?: string }): EffectHandle;\n};\n\nexport const createWatch =\n (runtime: WatchRuntime) =>\n <T>(\n source: Readable<T> | (() => T),\n callback: (value: T, previous: T | undefined) => void,\n options?: WatchOptions<T>,\n ): EffectHandle => {\n const read = typeof source === 'function' ? source : () => source.value;\n const equals = options?.equals ?? Object.is;\n let initial = true;\n let previous: T | undefined;\n // `handle` is in the temporal dead zone during the effect's initial synchronous run —\n // `runtime.effect()` calls `node.run()` before returning. Defer disposal until after\n // the constructor returns so `handle.dispose()` is reachable from inside the callback.\n let disposeAfterInit = false;\n\n const handle = runtime.effect(\n () => {\n const value = read();\n\n if (initial) {\n initial = false;\n previous = value;\n\n if (options?.immediate) {\n callback(value, undefined);\n if (options?.once) disposeAfterInit = true;\n }\n\n return;\n }\n\n if (equals(previous as T, value)) return;\n\n const oldValue = previous;\n\n previous = value;\n callback(value, oldValue);\n\n if (options?.once) handle.dispose();\n },\n { name: options?.name },\n );\n\n if (disposeAfterInit) handle.dispose();\n\n return handle;\n };\n","import { createResource, type Resource, type ResourceOptions } from './_async';\nimport { createWatch, type WatchOptions } from './_watch';\nimport { ReactiveRuntime } from './runtime';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n} from './types';\n\nexport interface Ripple {\n batch<T>(fn: () => T): T;\n computed<T>(derive: () => T, options?: ComputedOptions<T>): Readable<T>;\n createScope(name?: string): Scope;\n dispose(): void;\n readonly disposed: boolean;\n effect(callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle;\n resource<Source, Value>(\n source: () => Source,\n loader: (source: Source, context: { readonly signal: AbortSignal }) => Promise<Value>,\n options?: ResourceOptions,\n ): Resource<Value>;\n signal<T>(initial: T, options?: SignalOptions<T>): Signal<T>;\n untrack<T>(fn: () => T): T;\n watch<T>(\n source: Readable<T> | (() => T),\n callback: (value: T, previous: T | undefined) => void,\n options?: WatchOptions<T>,\n ): EffectHandle;\n}\n\n/** Creates one complete reactive graph. All factories on the object share its runtime. */\nexport const createRipple = (options?: RippleOptions): Ripple => {\n const runtime = new ReactiveRuntime(options);\n const resource = createResource(runtime);\n\n return {\n batch: runtime.batch,\n computed: runtime.computed,\n createScope: runtime.createScope,\n dispose: () => runtime.dispose(),\n get disposed() {\n return runtime.disposed;\n },\n effect: runtime.effect,\n resource,\n signal: runtime.signal,\n untrack: runtime.untrack,\n watch: createWatch(runtime),\n };\n};\n\n/**\n * The shared default reactive graph. Private — `signal`, `computed`, `effect`, `batch`,\n * `createScope`, `untrack`, `watch`, and `resource` are re-exported from the package root\n * as bound methods on this single graph instance.\n */\nexport const defaultRipple = createRipple();\n","export type { AsyncState, Resource, ResourceOptions } from './_async';\nexport { createRipple, type Ripple } from './_default';\nexport type { WatchOptions } from './_watch';\nexport {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleError,\n RippleInfiniteLoopError,\n} from './errors';\nexport { isReactive } from './runtime';\nexport type {\n Cleanup,\n ComputedOptions,\n Disposable,\n EffectHandle,\n EffectOptions,\n Equality,\n ReactiveErrorContext,\n ReactiveEvent,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nimport { defaultRipple } from './_default';\n\nexport const signal = defaultRipple.signal;\nexport const computed = defaultRipple.computed;\nexport const effect = defaultRipple.effect;\nexport const batch = defaultRipple.batch;\nexport const createScope = defaultRipple.createScope;\nexport const untrack = defaultRipple.untrack;\nexport const watch = defaultRipple.watch;\nexport const resource = defaultRipple.resource;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ripple.js","names":[],"sources":["../src/errors.ts","../src/runtime.ts","../src/_async.ts","../src/_watch.ts","../src/_default.ts","../src/index.ts"],"sourcesContent":["export class RippleError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\nexport class RippleComputedCycleError extends RippleError {}\nexport class RippleDisposedRuntimeError extends RippleError {}\nexport class RippleDisposedScopeError extends RippleError {}\nexport class RippleInfiniteLoopError extends RippleError {}\n","import {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleInfiniteLoopError,\n} from './errors';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n ReactiveErrorContext,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nexport const REACTIVE = Symbol.for('@vielzeug/ripple/reactive');\nconst MAX_FLUSH_ITERATIONS = 100;\nconst UNSET = Symbol('ripple.unset');\n\ntype Dependency = ReactiveNode<unknown>;\n\ntype ObserverNode = {\n collecting?: Set<Dependency>;\n readonly dependencies: Set<Dependency>;\n onDependencyChanged(): void;\n};\n\ntype Owned = {\n dispose(): void;\n};\n\nabstract class ReactiveNode<T> {\n readonly [REACTIVE] = true;\n readonly dependents = new Set<ObserverNode>();\n readonly name: string | undefined;\n protected readonly runtime: ReactiveRuntime;\n\n protected constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n abstract peek(): T;\n abstract get value(): T;\n\n subscribe(listener: () => void): Unsubscribe {\n this.runtime.assertActive();\n this.peek();\n\n const observer: ObserverNode = {\n dependencies: new Set(),\n onDependencyChanged: () => this.runtime.enqueueListener(listener),\n };\n\n this.dependents.add(observer);\n\n return () => this.dependents.delete(observer);\n }\n\n protected notify(): void {\n for (const dependent of [...this.dependents]) dependent.onDependencyChanged();\n }\n}\n\nclass SignalNode<T> extends ReactiveNode<T> implements Signal<T> {\n private current: T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, initial: T, options?: SignalOptions<T>) {\n super(runtime, options?.name);\n this.current = initial;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.runtime.track(this);\n\n return this.current;\n }\n\n set value(next: T) {\n this.runtime.assertActive();\n\n if (this.equals(this.current, next)) return;\n\n const previous = this.current;\n\n this.current = next;\n this.runtime.emit({ kind: 'write', name: this.name, next, previous });\n this.runtime.propagate(() => this.notify());\n }\n\n peek(): T {\n return this.current;\n }\n\n update(updater: (prev: T) => T): void {\n this.value = updater(this.current);\n }\n}\n\nclass ComputedNode<T> extends ReactiveNode<T> implements ObserverNode, Owned {\n readonly dependencies = new Set<Dependency>();\n private computing = false;\n private disposed = false;\n private dirty = true;\n private current: T | typeof UNSET = UNSET;\n private readonly derive: () => T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, derive: () => T, options?: ComputedOptions<T>) {\n super(runtime, options?.name);\n this.derive = derive;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n // Track before refresh: if refresh throws, the consumer still depends on\n // this computed and must be notified when a dependency change might let it\n // succeed. Without this, a first-run failure permanently severs the\n // consumer from the computed.\n this.runtime.track(this);\n this.refresh();\n\n return this.current as T;\n }\n\n peek(): T {\n this.refresh();\n\n return this.current as T;\n }\n\n onDependencyChanged(): void {\n if (this.disposed) return;\n\n if (!this.dirty) this.dirty = true;\n\n if (this.dependents.size > 0 && this.refresh()) this.notify();\n }\n\n dispose(): void {\n if (this.disposed) return;\n\n this.disposed = true;\n this.runtime.clearDependencies(this);\n this.dependents.clear();\n }\n\n private refresh(): boolean {\n if (!this.dirty || this.disposed) return false;\n\n if (this.computing) {\n const label = this.name === undefined ? '' : ` \"${this.name}\"`;\n\n throw new RippleComputedCycleError(`computed cycle detected${label}`);\n }\n\n this.computing = true;\n this.runtime.emit({ kind: 'compute', name: this.name });\n\n try {\n const next = this.runtime.collect(this, this.derive);\n const changed = this.current === UNSET || !this.equals(this.current as T, next);\n\n this.current = next;\n this.dirty = false;\n\n return changed;\n } finally {\n this.computing = false;\n }\n }\n}\n\nclass ScopeNode implements Scope {\n readonly disposalController = new AbortController();\n readonly owned = new Set<Owned>();\n readonly name: string | undefined;\n private isDisposed = false;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n run<T>(fn: () => T): T {\n if (this.isDisposed) throw new RippleDisposedScopeError('Cannot run a disposed scope.');\n\n return this.runtime.withScope(this, fn);\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n for (const owned of [...this.owned].reverse()) owned.dispose();\n this.owned.clear();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.name, node: 'scope' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nclass EffectNode implements ObserverNode, EffectHandle {\n readonly dependencies = new Set<Dependency>();\n readonly disposalController = new AbortController();\n private cleanup: Cleanup | undefined;\n private isDisposed = false;\n private owner: ScopeNode | undefined;\n private scheduled = false;\n private readonly callback: () => Cleanup | undefined;\n private readonly options: EffectOptions | undefined;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, callback: () => Cleanup | undefined, options?: EffectOptions) {\n this.runtime = runtime;\n this.callback = callback;\n this.options = options;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n onDependencyChanged(): void {\n if (this.isDisposed) return;\n\n if (this.options?.scheduler === 'microtask') {\n if (this.scheduled) return;\n\n this.scheduled = true;\n queueMicrotask(() => {\n this.scheduled = false;\n\n if (!this.isDisposed) this.runtime.enqueue(this);\n });\n\n return;\n }\n\n this.runtime.enqueue(this);\n }\n\n run(): void {\n if (this.isDisposed) return;\n\n this.owner?.dispose();\n this.owner = undefined;\n this.runCleanup();\n this.runtime.emit({ kind: 'effect', name: this.options?.name });\n\n const owner = new ScopeNode(this.runtime);\n\n try {\n const cleanup = this.runtime.withEffectScope(owner, () => this.runtime.collectEffect(this, this.callback));\n\n this.owner = owner;\n this.cleanup = typeof cleanup === 'function' ? cleanup : undefined;\n } catch (error) {\n owner.dispose();\n this.runtime.report(error, { kind: 'effect', name: this.options?.name });\n }\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.owner?.dispose();\n this.owner = undefined;\n this.runtime.clearDependencies(this);\n this.runCleanup();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.options?.name, node: 'effect' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n private runCleanup(): void {\n const cleanup = this.cleanup;\n\n this.cleanup = undefined;\n\n if (cleanup === undefined) return;\n\n try {\n cleanup();\n } catch (error) {\n this.runtime.report(error, { kind: 'cleanup', name: this.options?.name });\n }\n }\n}\n\n/**\n * A runtime owns reactive graph state and lifetime. Separate instances isolate\n * applications and SSR requests without process-wide mutable hooks.\n */\nexport class ReactiveRuntime {\n private activeEffectScope: ScopeNode | undefined;\n private activeObserver: ObserverNode | undefined;\n private activeScope: ScopeNode;\n private isDisposed = false;\n private flushDepth = 0;\n private flushing = false;\n private readonly pending = new Set<EffectNode>();\n private readonly listeners = new Set<() => void>();\n private readonly rootScope: ScopeNode;\n private readonly observer: ReactiveObserver | undefined;\n private readonly onError: (error: unknown, context: ReactiveErrorContext) => void;\n\n constructor(options?: RippleOptions) {\n this.observer = options?.observer;\n this.onError =\n options?.onError ??\n ((error) => {\n queueMicrotask(() => {\n throw error;\n });\n });\n this.rootScope = new ScopeNode(this, 'runtime');\n this.activeScope = this.rootScope;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n readonly signal = <T>(initial: T, options?: SignalOptions<T>): Signal<T> => {\n this.assertActive();\n\n return new SignalNode(this, initial, options);\n };\n\n readonly computed = <T>(derive: () => T, options?: ComputedOptions<T>): Readable<T> => {\n this.assertActive();\n\n const node = new ComputedNode(this, derive, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n\n return node;\n };\n\n readonly effect = (callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle => {\n this.assertActive();\n\n const node = new EffectNode(this, callback, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n node.run();\n\n return node;\n };\n\n readonly createScope = (name?: string): Scope => {\n this.assertActive();\n\n const scope = new ScopeNode(this, name);\n\n // Scopes model explicit, caller-owned lifetimes. Unlike effects/computeds created during an\n // effect run, they deliberately attach to the enclosing scope rather than the per-run owner:\n // keyed DOM directives retain item scopes across reconciliation runs and dispose them only\n // when the item itself leaves the collection.\n this.activeScope.owned.add(scope);\n\n return scope;\n };\n\n readonly batch = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.propagate(fn);\n };\n\n readonly untrack = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.withObserver(undefined, fn);\n };\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.rootScope.dispose();\n }\n\n /** Internal node guard: disposed runtimes allow inert reads but reject graph work and mutation. */\n assertActive(): void {\n if (this.isDisposed) throw new RippleDisposedRuntimeError('Cannot use a disposed Ripple runtime.');\n }\n\n track(node: Dependency): void {\n const observer = this.activeObserver;\n\n if (observer?.collecting === undefined) return;\n\n observer.collecting.add(node);\n }\n\n clearDependencies(observer: ObserverNode): void {\n for (const dependency of observer.dependencies) dependency.dependents.delete(observer);\n observer.dependencies.clear();\n }\n\n collect<T>(observer: ObserverNode, fn: () => T): T {\n // On first run (no prior dependencies), commit partial dependencies even if\n // derive throws — otherwise the computed would have zero dependencies and never\n // be notified when its source changes, permanently stuck until a manual read.\n // On subsequent runs, keep previous dependencies (tested behavior).\n return this.collectWith(observer, fn, observer.dependencies.size === 0);\n }\n\n collectEffect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, true);\n }\n\n withEffectScope<T>(scope: ScopeNode, fn: () => T): T {\n const previous = this.activeEffectScope;\n\n this.activeEffectScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previous;\n }\n }\n\n withObserver<T>(observer: ObserverNode | undefined, fn: () => T): T {\n const previous = this.activeObserver;\n\n this.activeObserver = observer;\n\n try {\n return fn();\n } finally {\n this.activeObserver = previous;\n }\n }\n\n withScope<T>(scope: ScopeNode, fn: () => T): T {\n const previousEffectScope = this.activeEffectScope;\n const previousScope = this.activeScope;\n\n this.activeEffectScope = undefined;\n this.activeScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previousEffectScope;\n this.activeScope = previousScope;\n }\n }\n\n enqueue(effect: EffectNode): void {\n this.pending.add(effect);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n enqueueListener(listener: () => void): void {\n this.listeners.add(listener);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n propagate<T>(fn: () => T): T {\n this.flushDepth++;\n\n try {\n return fn();\n } finally {\n this.flushDepth--;\n\n if (this.flushDepth === 0) this.flush();\n }\n }\n\n emit(event: Parameters<ReactiveObserver>[0]): void {\n try {\n this.observer?.(event);\n } catch (error) {\n this.report(error, { kind: 'observer', name: event.name });\n }\n }\n\n report(error: unknown, context: ReactiveErrorContext): void {\n try {\n this.onError(error, context);\n } catch (reporterError) {\n queueMicrotask(() => {\n throw reporterError;\n });\n }\n }\n\n private collectWith<T>(observer: ObserverNode, fn: () => T, commitOnError: boolean): T {\n const previousObserver = this.activeObserver;\n const dependencies = new Set<Dependency>();\n\n observer.collecting = dependencies;\n this.activeObserver = observer;\n\n try {\n const result = fn();\n\n this.commitDependencies(observer, dependencies);\n\n return result;\n } catch (error) {\n if (commitOnError) this.commitDependencies(observer, dependencies);\n\n throw error;\n } finally {\n observer.collecting = undefined;\n this.activeObserver = previousObserver;\n }\n }\n\n private commitDependencies(observer: ObserverNode, next: Set<Dependency>): void {\n for (const dependency of observer.dependencies) {\n if (!next.has(dependency)) dependency.dependents.delete(observer);\n }\n\n for (const dependency of next) {\n if (!observer.dependencies.has(dependency)) dependency.dependents.add(observer);\n }\n\n observer.dependencies.clear();\n for (const dependency of next) observer.dependencies.add(dependency);\n }\n\n private flush(): void {\n if (this.flushing) return;\n\n this.flushing = true;\n\n let iterations = 0;\n\n try {\n while (this.pending.size > 0 || this.listeners.size > 0) {\n if (++iterations > MAX_FLUSH_ITERATIONS) {\n throw new RippleInfiniteLoopError(`infinite reactive flush (>${MAX_FLUSH_ITERATIONS} iterations)`);\n }\n\n const effects = [...this.pending];\n const listeners = [...this.listeners];\n\n this.pending.clear();\n this.listeners.clear();\n\n for (const effect of effects) effect.run();\n\n for (const listener of listeners) {\n try {\n listener();\n } catch (error) {\n this.report(error, { kind: 'listener' });\n }\n }\n }\n } finally {\n this.flushing = false;\n }\n }\n}\n\nexport const isReactive = <T>(value: T | Readable<T>): value is Readable<T> => {\n if (typeof value !== 'object' || value === null || !(REACTIVE in value)) return false;\n\n const candidate = value as { peek?: unknown; subscribe?: unknown };\n\n return typeof candidate.peek === 'function' && typeof candidate.subscribe === 'function';\n};\n","import { REACTIVE } from './runtime';\nimport type { Disposable, EffectHandle, Readable, Signal } from './types';\n\nexport type AsyncState<T> =\n | { readonly previous?: T; readonly status: 'pending' }\n | { readonly status: 'success'; readonly value: T }\n | { readonly error: unknown; readonly previous?: T; readonly status: 'error' };\n\nexport interface Resource<T> extends Readable<AsyncState<T>>, Disposable {\n reload(): void;\n}\n\nexport type ResourceOptions = {\n name?: string;\n};\n\ntype AsyncRuntime = {\n effect(callback: () => undefined | (() => void), options?: { name?: string }): EffectHandle;\n signal<T>(initial: T, options?: { name?: string }): Signal<T>;\n};\n\n/** Resource only depends on primitive runtime methods; graph binding stays private. */\nexport const createResource =\n (runtime: AsyncRuntime) =>\n <Source, Value>(\n source: () => Source,\n loader: (source: Source, context: { readonly signal: AbortSignal }) => Promise<Value>,\n options?: ResourceOptions,\n ): Resource<Value> => {\n const state = runtime.signal<AsyncState<Value>>({ status: 'pending' }, { name: options?.name });\n const reloadEpoch = runtime.signal(0);\n let active: AbortController | undefined;\n let disposed = false;\n\n const run = (): void => {\n void reloadEpoch.value;\n active?.abort();\n\n const current = state.peek();\n const previous =\n current.status === 'success' ? current.value : 'previous' in current ? current.previous : undefined;\n let input: Source;\n\n try {\n input = source();\n } catch (error) {\n state.value = previous === undefined ? { error, status: 'error' } : { error, previous, status: 'error' };\n\n return;\n }\n\n const next = new AbortController();\n\n active = next;\n state.value = previous === undefined ? { status: 'pending' } : { previous, status: 'pending' };\n\n let request: Promise<Value>;\n\n try {\n request = Promise.resolve(loader(input, { signal: next.signal }));\n } catch (error) {\n request = Promise.reject(error);\n }\n\n void request.then(\n (value) => {\n if (!disposed && !next.signal.aborted) state.value = { status: 'success', value };\n },\n (error: unknown) => {\n if (!disposed && !next.signal.aborted) {\n state.value = previous === undefined ? { error, status: 'error' } : { error, previous, status: 'error' };\n }\n },\n );\n };\n\n const stop = runtime.effect(\n () => {\n run();\n\n return () => active?.abort();\n },\n { name: options?.name },\n );\n\n stop.disposalSignal.addEventListener(\n 'abort',\n () => {\n disposed = true;\n },\n { once: true },\n );\n\n const resource: Resource<Value> = {\n get disposalSignal() {\n return stop.disposalSignal;\n },\n dispose: () => stop.dispose(),\n get disposed() {\n return disposed;\n },\n get name() {\n return state.name;\n },\n peek: () => state.peek(),\n reload: () => {\n if (disposed) return;\n\n reloadEpoch.value = reloadEpoch.peek() + 1;\n },\n subscribe: (listener) => state.subscribe(listener),\n [Symbol.dispose]() {\n this.dispose();\n },\n get value() {\n return state.value;\n },\n };\n\n Object.defineProperty(resource, REACTIVE, { value: true });\n\n return resource;\n };\n","import type { EffectHandle, Equality, Readable } from './types';\n\nexport type WatchOptions<T> = {\n equals?: Equality<T>;\n immediate?: boolean;\n name?: string;\n once?: boolean;\n};\n\ntype WatchRuntime = {\n effect(callback: () => undefined | (() => void), options?: { name?: string }): EffectHandle;\n};\n\nexport const createWatch =\n (runtime: WatchRuntime) =>\n <T>(\n source: Readable<T> | (() => T),\n callback: (value: T, previous: T | undefined) => void,\n options?: WatchOptions<T>,\n ): EffectHandle => {\n const read = typeof source === 'function' ? source : () => source.value;\n const equals = options?.equals ?? Object.is;\n let initial = true;\n let previous: T | undefined;\n // `handle` is in the temporal dead zone during the effect's initial synchronous run —\n // `runtime.effect()` calls `node.run()` before returning. Defer disposal until after\n // the constructor returns so `handle.dispose()` is reachable from inside the callback.\n let disposeAfterInit = false;\n\n const handle = runtime.effect(\n () => {\n const value = read();\n\n if (initial) {\n initial = false;\n previous = value;\n\n if (options?.immediate) {\n callback(value, undefined);\n if (options?.once) disposeAfterInit = true;\n }\n\n return;\n }\n\n if (equals(previous as T, value)) return;\n\n const oldValue = previous;\n\n previous = value;\n callback(value, oldValue);\n\n if (options?.once) handle.dispose();\n },\n { name: options?.name },\n );\n\n if (disposeAfterInit) handle.dispose();\n\n return handle;\n };\n","import { createResource, type Resource, type ResourceOptions } from './_async';\nimport { createWatch, type WatchOptions } from './_watch';\nimport { ReactiveRuntime } from './runtime';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n} from './types';\n\nexport interface Ripple {\n batch<T>(fn: () => T): T;\n computed<T>(derive: () => T, options?: ComputedOptions<T>): Readable<T>;\n createScope(name?: string): Scope;\n dispose(): void;\n readonly disposed: boolean;\n effect(callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle;\n resource<Source, Value>(\n source: () => Source,\n loader: (source: Source, context: { readonly signal: AbortSignal }) => Promise<Value>,\n options?: ResourceOptions,\n ): Resource<Value>;\n signal<T>(initial: T, options?: SignalOptions<T>): Signal<T>;\n untrack<T>(fn: () => T): T;\n watch<T>(\n source: Readable<T> | (() => T),\n callback: (value: T, previous: T | undefined) => void,\n options?: WatchOptions<T>,\n ): EffectHandle;\n}\n\n/** Creates one complete reactive graph. All factories on the object share its runtime. */\nexport const createRipple = (options?: RippleOptions): Ripple => {\n const runtime = new ReactiveRuntime(options);\n const resource = createResource(runtime);\n\n return {\n batch: runtime.batch,\n computed: runtime.computed,\n createScope: runtime.createScope,\n dispose: () => runtime.dispose(),\n get disposed() {\n return runtime.disposed;\n },\n effect: runtime.effect,\n resource,\n signal: runtime.signal,\n untrack: runtime.untrack,\n watch: createWatch(runtime),\n };\n};\n\n/**\n * The shared default reactive graph. Private — `signal`, `computed`, `effect`, `batch`,\n * `createScope`, `untrack`, `watch`, and `resource` are re-exported from the package root\n * as bound methods on this single graph instance.\n */\nexport const defaultRipple = createRipple();\n","export type { AsyncState, Resource, ResourceOptions } from './_async';\nexport { createRipple, type Ripple } from './_default';\nexport type { WatchOptions } from './_watch';\nexport {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleError,\n RippleInfiniteLoopError,\n} from './errors';\nexport { isReactive } from './runtime';\nexport type {\n Cleanup,\n ComputedOptions,\n Disposable,\n EffectHandle,\n EffectOptions,\n Equality,\n ReactiveErrorContext,\n ReactiveEvent,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nimport { defaultRipple } from './_default';\n\nexport const signal = defaultRipple.signal;\nexport const computed = defaultRipple.computed;\nexport const effect = defaultRipple.effect;\nexport const batch = defaultRipple.batch;\nexport const createScope = defaultRipple.createScope;\nexport const untrack = defaultRipple.untrack;\nexport const watch = defaultRipple.watch;\nexport const resource = defaultRipple.resource;\n"],"mappings":"AAAA,IAAa,EAAb,cAAiC,KAAM,CACrC,YAAY,EAAiB,EAAwB,CACnD,MAAM,EAAS,CAAO,EACtB,KAAK,KAAO,WAAW,KACvB,OAAO,eAAe,KAAM,WAAW,SAAS,CAClD,CACF,EAEa,EAAb,cAA8C,CAAY,CAAC,EAC9C,EAAb,cAAgD,CAAY,CAAC,EAChD,EAAb,cAA8C,CAAY,CAAC,EAC9C,EAAb,cAA6C,CAAY,CAAC,ECU7C,EAAW,OAAO,IAAI,2BAA2B,EACxD,EAAuB,IACvB,EAAQ,OAAO,cAAc,EAcpB,EAAf,KAA+B,CAC7B,CAAU,GAAY,GACtB,WAAsB,IAAI,IAC1B,KACA,QAEA,YAAsB,EAA0B,EAAe,CAC7D,KAAK,QAAU,EACf,KAAK,KAAO,CACd,CAKA,UAAU,EAAmC,CAC3C,KAAK,QAAQ,aAAa,EAC1B,KAAK,KAAK,EAEV,IAAM,EAAyB,CAC7B,aAAc,IAAI,IAClB,wBAA2B,KAAK,QAAQ,gBAAgB,CAAQ,CAClE,EAIA,OAFA,KAAK,WAAW,IAAI,CAAQ,MAEf,KAAK,WAAW,OAAO,CAAQ,CAC9C,CAEA,QAAyB,CACvB,IAAK,IAAM,IAAa,CAAC,GAAG,KAAK,UAAU,EAAG,EAAU,oBAAoB,CAC9E,CACF,EAEM,EAAN,cAA4B,CAAqC,CAC/D,QACA,OAEA,YAAY,EAA0B,EAAY,EAA4B,CAC5E,MAAM,EAAS,GAAS,IAAI,EAC5B,KAAK,QAAU,EACf,KAAK,OAAS,GAAS,QAAU,OAAO,EAC1C,CAEA,IAAI,OAAW,CAGb,OAFA,KAAK,QAAQ,MAAM,IAAI,EAEhB,KAAK,OACd,CAEA,IAAI,MAAM,EAAS,CAGjB,GAFA,KAAK,QAAQ,aAAa,EAEtB,KAAK,OAAO,KAAK,QAAS,CAAI,EAAG,OAErC,IAAM,EAAW,KAAK,QAEtB,KAAK,QAAU,EACf,KAAK,QAAQ,KAAK,CAAE,KAAM,QAAS,KAAM,KAAK,KAAM,OAAM,UAAS,CAAC,EACpE,KAAK,QAAQ,cAAgB,KAAK,OAAO,CAAC,CAC5C,CAEA,MAAU,CACR,OAAO,KAAK,OACd,CAEA,OAAO,EAA+B,CACpC,KAAK,MAAQ,EAAQ,KAAK,OAAO,CACnC,CACF,EAEM,EAAN,cAA8B,CAA+C,CAC3E,aAAwB,IAAI,IAC5B,UAAoB,GACpB,SAAmB,GACnB,MAAgB,GAChB,QAAoC,EACpC,OACA,OAEA,YAAY,EAA0B,EAAiB,EAA8B,CACnF,MAAM,EAAS,GAAS,IAAI,EAC5B,KAAK,OAAS,EACd,KAAK,OAAS,GAAS,QAAU,OAAO,EAC1C,CAEA,IAAI,OAAW,CAQb,OAHA,KAAK,QAAQ,MAAM,IAAI,EACvB,KAAK,QAAQ,EAEN,KAAK,OACd,CAEA,MAAU,CAGR,OAFA,KAAK,QAAQ,EAEN,KAAK,OACd,CAEA,qBAA4B,CACtB,KAAK,WAET,AAAiB,KAAK,QAAQ,GAE1B,KAAK,WAAW,KAAO,GAAK,KAAK,QAAQ,GAAG,KAAK,OAAO,EAC9D,CAEA,SAAgB,CACV,KAAK,WAET,KAAK,SAAW,GAChB,KAAK,QAAQ,kBAAkB,IAAI,EACnC,KAAK,WAAW,MAAM,EACxB,CAEA,SAA2B,CACzB,GAAI,CAAC,KAAK,OAAS,KAAK,SAAU,MAAO,GAEzC,GAAI,KAAK,UAGP,MAAM,IAAI,EAAyB,0BAFrB,KAAK,OAAS,IAAA,GAAY,GAAK,KAAK,KAAK,KAAK,IAEQ,EAGtE,KAAK,UAAY,GACjB,KAAK,QAAQ,KAAK,CAAE,KAAM,UAAW,KAAM,KAAK,IAAK,CAAC,EAEtD,GAAI,CACF,IAAM,EAAO,KAAK,QAAQ,QAAQ,KAAM,KAAK,MAAM,EAC7C,EAAU,KAAK,UAAY,GAAS,CAAC,KAAK,OAAO,KAAK,QAAc,CAAI,EAK9E,MAHA,MAAK,QAAU,EACf,KAAK,MAAQ,GAEN,CACT,QAAU,CACR,KAAK,UAAY,EACnB,CACF,CACF,EAEM,EAAN,KAAiC,CAC/B,mBAA8B,IAAI,gBAClC,MAAiB,IAAI,IACrB,KACA,WAAqB,GACrB,QAEA,YAAY,EAA0B,EAAe,CACnD,KAAK,QAAU,EACf,KAAK,KAAO,CACd,CAEA,IAAI,UAAoB,CACtB,OAAO,KAAK,UACd,CAEA,IAAI,gBAA8B,CAChC,OAAO,KAAK,mBAAmB,MACjC,CAEA,IAAO,EAAgB,CACrB,GAAI,KAAK,WAAY,MAAM,IAAI,EAAyB,8BAA8B,EAEtF,OAAO,KAAK,QAAQ,UAAU,KAAM,CAAE,CACxC,CAEA,SAAgB,CACV,SAAK,WAET,MAAK,WAAa,GAClB,IAAK,IAAM,IAAS,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,QAAQ,EAAG,EAAM,QAAQ,EAC7D,KAAK,MAAM,MAAM,EACjB,KAAK,mBAAmB,MAAM,EAC9B,KAAK,QAAQ,KAAK,CAAE,KAAM,UAAW,KAAM,KAAK,KAAM,KAAM,OAAQ,CAAC,CAJnD,CAKpB,CAEA,CAAC,OAAO,UAAiB,CACvB,KAAK,QAAQ,CACf,CACF,EAEM,EAAN,KAAuD,CACrD,aAAwB,IAAI,IAC5B,mBAA8B,IAAI,gBAClC,QACA,WAAqB,GACrB,MACA,UAAoB,GACpB,SACA,QACA,QAEA,YAAY,EAA0B,EAAqC,EAAyB,CAClG,KAAK,QAAU,EACf,KAAK,SAAW,EAChB,KAAK,QAAU,CACjB,CAEA,IAAI,UAAoB,CACtB,OAAO,KAAK,UACd,CAEA,IAAI,gBAA8B,CAChC,OAAO,KAAK,mBAAmB,MACjC,CAEA,qBAA4B,CACtB,SAAK,WAET,IAAI,KAAK,SAAS,YAAc,YAAa,CAC3C,GAAI,KAAK,UAAW,OAEpB,KAAK,UAAY,GACjB,mBAAqB,CACnB,KAAK,UAAY,GAEZ,KAAK,YAAY,KAAK,QAAQ,QAAQ,IAAI,CACjD,CAAC,EAED,MACF,CAEA,KAAK,QAAQ,QAAQ,IAAI,CAFzB,CAGF,CAEA,KAAY,CACV,GAAI,KAAK,WAAY,OAErB,KAAK,OAAO,QAAQ,EACpB,KAAK,MAAQ,IAAA,GACb,KAAK,WAAW,EAChB,KAAK,QAAQ,KAAK,CAAE,KAAM,SAAU,KAAM,KAAK,SAAS,IAAK,CAAC,EAE9D,IAAM,EAAQ,IAAI,EAAU,KAAK,OAAO,EAExC,GAAI,CACF,IAAM,EAAU,KAAK,QAAQ,gBAAgB,MAAa,KAAK,QAAQ,cAAc,KAAM,KAAK,QAAQ,CAAC,EAEzG,KAAK,MAAQ,EACb,KAAK,QAAU,OAAO,GAAY,WAAa,EAAU,IAAA,EAC3D,OAAS,EAAO,CACd,EAAM,QAAQ,EACd,KAAK,QAAQ,OAAO,EAAO,CAAE,KAAM,SAAU,KAAM,KAAK,SAAS,IAAK,CAAC,CACzE,CACF,CAEA,SAAgB,CACV,KAAK,aAET,KAAK,WAAa,GAClB,KAAK,OAAO,QAAQ,EACpB,KAAK,MAAQ,IAAA,GACb,KAAK,QAAQ,kBAAkB,IAAI,EACnC,KAAK,WAAW,EAChB,KAAK,mBAAmB,MAAM,EAC9B,KAAK,QAAQ,KAAK,CAAE,KAAM,UAAW,KAAM,KAAK,SAAS,KAAM,KAAM,QAAS,CAAC,EACjF,CAEA,CAAC,OAAO,UAAiB,CACvB,KAAK,QAAQ,CACf,CAEA,YAA2B,CACzB,IAAM,EAAU,KAAK,QAErB,QAAK,QAAU,IAAA,GAEX,IAAY,IAAA,GAEhB,GAAI,CACF,EAAQ,CACV,OAAS,EAAO,CACd,KAAK,QAAQ,OAAO,EAAO,CAAE,KAAM,UAAW,KAAM,KAAK,SAAS,IAAK,CAAC,CAC1E,CACF,CACF,EAMa,EAAb,KAA6B,CAC3B,kBACA,eACA,YACA,WAAqB,GACrB,WAAqB,EACrB,SAAmB,GACnB,QAA2B,IAAI,IAC/B,UAA6B,IAAI,IACjC,UACA,SACA,QAEA,YAAY,EAAyB,CACnC,KAAK,SAAW,GAAS,SACzB,KAAK,QACH,GAAS,UACP,GAAU,CACV,mBAAqB,CACnB,MAAM,CACR,CAAC,CACH,GACF,KAAK,UAAY,IAAI,EAAU,KAAM,SAAS,EAC9C,KAAK,YAAc,KAAK,SAC1B,CAEA,IAAI,UAAoB,CACtB,OAAO,KAAK,UACd,CAEA,QAAsB,EAAY,KAChC,KAAK,aAAa,EAEX,IAAI,EAAW,KAAM,EAAS,CAAO,GAG9C,UAAwB,EAAiB,IAA8C,CACrF,KAAK,aAAa,EAElB,IAAM,EAAO,IAAI,EAAa,KAAM,EAAQ,CAAO,EAInD,OAFC,KAAK,mBAAqB,KAAK,YAAA,CAAa,MAAM,IAAI,CAAI,EAEpD,CACT,EAEA,QAAmB,EAAqC,IAA0C,CAChG,KAAK,aAAa,EAElB,IAAM,EAAO,IAAI,EAAW,KAAM,EAAU,CAAO,EAKnD,OAHC,KAAK,mBAAqB,KAAK,YAAA,CAAa,MAAM,IAAI,CAAI,EAC3D,EAAK,IAAI,EAEF,CACT,EAEA,YAAwB,GAAyB,CAC/C,KAAK,aAAa,EAElB,IAAM,EAAQ,IAAI,EAAU,KAAM,CAAI,EAQtC,OAFA,KAAK,YAAY,MAAM,IAAI,CAAK,EAEzB,CACT,EAEA,MAAqB,IACnB,KAAK,aAAa,EAEX,KAAK,UAAU,CAAE,GAG1B,QAAuB,IACrB,KAAK,aAAa,EAEX,KAAK,aAAa,IAAA,GAAW,CAAE,GAGxC,SAAgB,CACV,KAAK,aAET,KAAK,WAAa,GAClB,KAAK,UAAU,QAAQ,EACzB,CAGA,cAAqB,CACnB,GAAI,KAAK,WAAY,MAAM,IAAI,EAA2B,uCAAuC,CACnG,CAEA,MAAM,EAAwB,CAC5B,IAAM,EAAW,KAAK,eAElB,GAAU,aAAe,IAAA,IAE7B,EAAS,WAAW,IAAI,CAAI,CAC9B,CAEA,kBAAkB,EAA8B,CAC9C,IAAK,IAAM,KAAc,EAAS,aAAc,EAAW,WAAW,OAAO,CAAQ,EACrF,EAAS,aAAa,MAAM,CAC9B,CAEA,QAAW,EAAwB,EAAgB,CAKjD,OAAO,KAAK,YAAY,EAAU,EAAI,EAAS,aAAa,OAAS,CAAC,CACxE,CAEA,cAAiB,EAAwB,EAAgB,CACvD,OAAO,KAAK,YAAY,EAAU,EAAI,EAAI,CAC5C,CAEA,gBAAmB,EAAkB,EAAgB,CACnD,IAAM,EAAW,KAAK,kBAEtB,KAAK,kBAAoB,EAEzB,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,KAAK,kBAAoB,CAC3B,CACF,CAEA,aAAgB,EAAoC,EAAgB,CAClE,IAAM,EAAW,KAAK,eAEtB,KAAK,eAAiB,EAEtB,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,KAAK,eAAiB,CACxB,CACF,CAEA,UAAa,EAAkB,EAAgB,CAC7C,IAAM,EAAsB,KAAK,kBAC3B,EAAgB,KAAK,YAE3B,KAAK,kBAAoB,IAAA,GACzB,KAAK,YAAc,EAEnB,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,KAAK,kBAAoB,EACzB,KAAK,YAAc,CACrB,CACF,CAEA,QAAQ,EAA0B,CAChC,KAAK,QAAQ,IAAI,CAAM,EAEnB,KAAK,aAAe,GAAG,KAAK,MAAM,CACxC,CAEA,gBAAgB,EAA4B,CAC1C,KAAK,UAAU,IAAI,CAAQ,EAEvB,KAAK,aAAe,GAAG,KAAK,MAAM,CACxC,CAEA,UAAa,EAAgB,CAC3B,KAAK,aAEL,GAAI,CACF,OAAO,EAAG,CACZ,QAAU,CACR,KAAK,aAED,KAAK,aAAe,GAAG,KAAK,MAAM,CACxC,CACF,CAEA,KAAK,EAA8C,CACjD,GAAI,CACF,KAAK,WAAW,CAAK,CACvB,OAAS,EAAO,CACd,KAAK,OAAO,EAAO,CAAE,KAAM,WAAY,KAAM,EAAM,IAAK,CAAC,CAC3D,CACF,CAEA,OAAO,EAAgB,EAAqC,CAC1D,GAAI,CACF,KAAK,QAAQ,EAAO,CAAO,CAC7B,OAAS,EAAe,CACtB,mBAAqB,CACnB,MAAM,CACR,CAAC,CACH,CACF,CAEA,YAAuB,EAAwB,EAAa,EAA2B,CACrF,IAAM,EAAmB,KAAK,eACxB,EAAe,IAAI,IAEzB,EAAS,WAAa,EACtB,KAAK,eAAiB,EAEtB,GAAI,CACF,IAAM,EAAS,EAAG,EAIlB,OAFA,KAAK,mBAAmB,EAAU,CAAY,EAEvC,CACT,OAAS,EAAO,CAGd,MAFI,GAAe,KAAK,mBAAmB,EAAU,CAAY,EAE3D,CACR,QAAU,CACR,EAAS,WAAa,IAAA,GACtB,KAAK,eAAiB,CACxB,CACF,CAEA,mBAA2B,EAAwB,EAA6B,CAC9E,IAAK,IAAM,KAAc,EAAS,aAC3B,EAAK,IAAI,CAAU,GAAG,EAAW,WAAW,OAAO,CAAQ,EAGlE,IAAK,IAAM,KAAc,EAClB,EAAS,aAAa,IAAI,CAAU,GAAG,EAAW,WAAW,IAAI,CAAQ,EAGhF,EAAS,aAAa,MAAM,EAC5B,IAAK,IAAM,KAAc,EAAM,EAAS,aAAa,IAAI,CAAU,CACrE,CAEA,OAAsB,CACpB,GAAI,KAAK,SAAU,OAEnB,KAAK,SAAW,GAEhB,IAAI,EAAa,EAEjB,GAAI,CACF,KAAO,KAAK,QAAQ,KAAO,GAAK,KAAK,UAAU,KAAO,GAAG,CACvD,GAAI,EAAE,EAAa,EACjB,MAAM,IAAI,EAAwB,6BAA6B,EAAqB,aAAa,EAGnG,IAAM,EAAU,CAAC,GAAG,KAAK,OAAO,EAC1B,EAAY,CAAC,GAAG,KAAK,SAAS,EAEpC,KAAK,QAAQ,MAAM,EACnB,KAAK,UAAU,MAAM,EAErB,IAAK,IAAM,KAAU,EAAS,EAAO,IAAI,EAEzC,IAAK,IAAM,KAAY,EACrB,GAAI,CACF,EAAS,CACX,OAAS,EAAO,CACd,KAAK,OAAO,EAAO,CAAE,KAAM,UAAW,CAAC,CACzC,CAEJ,CACF,QAAU,CACR,KAAK,SAAW,EAClB,CACF,CACF,EAEa,EAAiB,GAAiD,CAC7E,GAAI,OAAO,GAAU,WAAY,GAAkB,EAAE,KAAY,GAAQ,MAAO,GAEhF,IAAM,EAAY,EAElB,OAAO,OAAO,EAAU,MAAS,YAAc,OAAO,EAAU,WAAc,UAChF,EClkBa,EACV,IAEC,EACA,EACA,IACoB,CACpB,IAAM,EAAQ,EAAQ,OAA0B,CAAE,OAAQ,SAAU,EAAG,CAAE,KAAM,GAAS,IAAK,CAAC,EACxF,EAAc,EAAQ,OAAO,CAAC,EAChC,EACA,EAAW,GAET,MAAkB,CACtB,EAAiB,MACjB,GAAQ,MAAM,EAEd,IAAM,EAAU,EAAM,KAAK,EACrB,EACJ,EAAQ,SAAW,UAAY,EAAQ,MAAQ,aAAc,EAAU,EAAQ,SAAW,IAAA,GACxF,EAEJ,GAAI,CACF,EAAQ,EAAO,CACjB,OAAS,EAAO,CACd,EAAM,MAAQ,IAAa,IAAA,GAAY,CAAE,QAAO,OAAQ,OAAQ,EAAI,CAAE,QAAO,WAAU,OAAQ,OAAQ,EAEvG,MACF,CAEA,IAAM,EAAO,IAAI,gBAEjB,EAAS,EACT,EAAM,MAAQ,IAAa,IAAA,GAAY,CAAE,OAAQ,SAAU,EAAI,CAAE,WAAU,OAAQ,SAAU,EAE7F,IAAI,EAEJ,GAAI,CACF,EAAU,QAAQ,QAAQ,EAAO,EAAO,CAAE,OAAQ,EAAK,MAAO,CAAC,CAAC,CAClE,OAAS,EAAO,CACd,EAAU,QAAQ,OAAO,CAAK,CAChC,CAEA,EAAa,KACV,GAAU,CACL,CAAC,GAAY,CAAC,EAAK,OAAO,UAAS,EAAM,MAAQ,CAAE,OAAQ,UAAW,OAAM,EAClF,EACC,GAAmB,CACd,CAAC,GAAY,CAAC,EAAK,OAAO,UAC5B,EAAM,MAAQ,IAAa,IAAA,GAAY,CAAE,QAAO,OAAQ,OAAQ,EAAI,CAAE,QAAO,WAAU,OAAQ,OAAQ,EAE3G,CACF,CACF,EAEM,EAAO,EAAQ,YAEjB,EAAI,MAES,GAAQ,MAAM,GAE7B,CAAE,KAAM,GAAS,IAAK,CACxB,EAEA,EAAK,eAAe,iBAClB,YACM,CACJ,EAAW,EACb,EACA,CAAE,KAAM,EAAK,CACf,EAEA,IAAM,EAA4B,CAChC,IAAI,gBAAiB,CACnB,OAAO,EAAK,cACd,EACA,YAAe,EAAK,QAAQ,EAC5B,IAAI,UAAW,CACb,OAAO,CACT,EACA,IAAI,MAAO,CACT,OAAO,EAAM,IACf,EACA,SAAY,EAAM,KAAK,EACvB,WAAc,CACR,IAEJ,EAAY,MAAQ,EAAY,KAAK,EAAI,EAC3C,EACA,UAAY,GAAa,EAAM,UAAU,CAAQ,EACjD,CAAC,OAAO,UAAW,CACjB,KAAK,QAAQ,CACf,EACA,IAAI,OAAQ,CACV,OAAO,EAAM,KACf,CACF,EAIA,OAFA,OAAO,eAAe,EAAU,EAAU,CAAE,MAAO,EAAK,CAAC,EAElD,CACT,EC7GW,EACV,IAEC,EACA,EACA,IACiB,CACjB,IAAM,EAAO,OAAO,GAAW,WAAa,MAAe,EAAO,MAC5D,EAAS,GAAS,QAAU,OAAO,GACrC,EAAU,GACV,EAIA,EAAmB,GAEjB,EAAS,EAAQ,WACf,CACJ,IAAM,EAAQ,EAAK,EAEnB,GAAI,EAAS,CACX,EAAU,GACV,EAAW,EAEP,GAAS,YACX,EAAS,EAAO,IAAA,EAAS,EACrB,GAAS,OAAM,EAAmB,KAGxC,MACF,CAEA,GAAI,EAAO,EAAe,CAAK,EAAG,OAElC,IAAM,EAAW,EAEjB,EAAW,EACX,EAAS,EAAO,CAAQ,EAEpB,GAAS,MAAM,EAAO,QAAQ,CACpC,EACA,CAAE,KAAM,GAAS,IAAK,CACxB,EAIA,OAFI,GAAkB,EAAO,QAAQ,EAE9B,CACT,ECvBW,EAAgB,GAAoC,CAC/D,IAAM,EAAU,IAAI,EAAgB,CAAO,EACrC,EAAW,EAAe,CAAO,EAEvC,MAAO,CACL,MAAO,EAAQ,MACf,SAAU,EAAQ,SAClB,YAAa,EAAQ,YACrB,YAAe,EAAQ,QAAQ,EAC/B,IAAI,UAAW,CACb,OAAO,EAAQ,QACjB,EACA,OAAQ,EAAQ,OAChB,WACA,OAAQ,EAAQ,OAChB,QAAS,EAAQ,QACjB,MAAO,EAAY,CAAO,CAC5B,CACF,EAOa,EAAgB,EAAa,EC/B7B,EAAS,EAAc,OACvB,EAAW,EAAc,SACzB,EAAS,EAAc,OACvB,EAAQ,EAAc,MACtB,EAAc,EAAc,YAC5B,EAAU,EAAc,QACxB,EAAQ,EAAc,MACtB,EAAW,EAAc"}
|
package/dist/runtime.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./errors.cjs");var t=Symbol.for(`@vielzeug/ripple/reactive`),n=100,r=Symbol(`ripple.unset`),i=class{[t]=!0;dependents=new Set;name;runtime;constructor(e,t){this.runtime=e,this.name=t}subscribe(e){this.runtime.assertActive(),this.peek();let t={dependencies:new Set,onDependencyChanged:()=>this.runtime.enqueueListener(e)};return this.dependents.add(t),()=>this.dependents.delete(t)}notify(){for(let e of[...this.dependents])e.onDependencyChanged()}},a=class extends i{current;equals;constructor(e,t,n){super(e,n?.name),this.current=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.current}set value(e){if(this.runtime.assertActive(),this.equals(this.current,e))return;let t=this.current;this.current=e,this.runtime.emit({kind:`write`,name:this.name,next:e,previous:t}),this.runtime.propagate(()=>this.notify())}peek(){return this.current}update(e){this.value=e(this.current)}},o=class extends i{dependencies=new Set;computing=!1;disposed=!1;dirty=!0;current=r;derive;equals;constructor(e,t,n){super(e,n?.name),this.derive=t,this.equals=n?.equals??Object.is}get value(){return this.
|
|
1
|
+
const e=require("./errors.cjs");var t=Symbol.for(`@vielzeug/ripple/reactive`),n=100,r=Symbol(`ripple.unset`),i=class{[t]=!0;dependents=new Set;name;runtime;constructor(e,t){this.runtime=e,this.name=t}subscribe(e){this.runtime.assertActive(),this.peek();let t={dependencies:new Set,onDependencyChanged:()=>this.runtime.enqueueListener(e)};return this.dependents.add(t),()=>this.dependents.delete(t)}notify(){for(let e of[...this.dependents])e.onDependencyChanged()}},a=class extends i{current;equals;constructor(e,t,n){super(e,n?.name),this.current=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.current}set value(e){if(this.runtime.assertActive(),this.equals(this.current,e))return;let t=this.current;this.current=e,this.runtime.emit({kind:`write`,name:this.name,next:e,previous:t}),this.runtime.propagate(()=>this.notify())}peek(){return this.current}update(e){this.value=e(this.current)}},o=class extends i{dependencies=new Set;computing=!1;disposed=!1;dirty=!0;current=r;derive;equals;constructor(e,t,n){super(e,n?.name),this.derive=t,this.equals=n?.equals??Object.is}get value(){return this.runtime.track(this),this.refresh(),this.current}peek(){return this.refresh(),this.current}onDependencyChanged(){this.disposed||(this.dirty||=!0,this.dependents.size>0&&this.refresh()&&this.notify())}dispose(){this.disposed||(this.disposed=!0,this.runtime.clearDependencies(this),this.dependents.clear())}refresh(){if(!this.dirty||this.disposed)return!1;if(this.computing){let t=this.name===void 0?``:` "${this.name}"`;throw new e.RippleComputedCycleError(`computed cycle detected${t}`)}this.computing=!0,this.runtime.emit({kind:`compute`,name:this.name});try{let e=this.runtime.collect(this,this.derive),t=this.current===r||!this.equals(this.current,e);return this.current=e,this.dirty=!1,t}finally{this.computing=!1}}},s=class{disposalController=new AbortController;owned=new Set;name;isDisposed=!1;runtime;constructor(e,t){this.runtime=e,this.name=t}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}run(t){if(this.isDisposed)throw new e.RippleDisposedScopeError(`Cannot run a disposed scope.`);return this.runtime.withScope(this,t)}dispose(){if(!this.isDisposed){this.isDisposed=!0;for(let e of[...this.owned].reverse())e.dispose();this.owned.clear(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.name,node:`scope`})}}[Symbol.dispose](){this.dispose()}},c=class{dependencies=new Set;disposalController=new AbortController;cleanup;isDisposed=!1;owner;scheduled=!1;callback;options;runtime;constructor(e,t,n){this.runtime=e,this.callback=t,this.options=n}get disposed(){return this.isDisposed}get disposalSignal(){return this.disposalController.signal}onDependencyChanged(){if(!this.isDisposed){if(this.options?.scheduler===`microtask`){if(this.scheduled)return;this.scheduled=!0,queueMicrotask(()=>{this.scheduled=!1,this.isDisposed||this.runtime.enqueue(this)});return}this.runtime.enqueue(this)}}run(){if(this.isDisposed)return;this.owner?.dispose(),this.owner=void 0,this.runCleanup(),this.runtime.emit({kind:`effect`,name:this.options?.name});let e=new s(this.runtime);try{let t=this.runtime.withEffectScope(e,()=>this.runtime.collectEffect(this,this.callback));this.owner=e,this.cleanup=typeof t==`function`?t:void 0}catch(t){e.dispose(),this.runtime.report(t,{kind:`effect`,name:this.options?.name})}}dispose(){this.isDisposed||(this.isDisposed=!0,this.owner?.dispose(),this.owner=void 0,this.runtime.clearDependencies(this),this.runCleanup(),this.disposalController.abort(),this.runtime.emit({kind:`dispose`,name:this.options?.name,node:`effect`}))}[Symbol.dispose](){this.dispose()}runCleanup(){let e=this.cleanup;if(this.cleanup=void 0,e!==void 0)try{e()}catch(e){this.runtime.report(e,{kind:`cleanup`,name:this.options?.name})}}},l=class{activeEffectScope;activeObserver;activeScope;isDisposed=!1;flushDepth=0;flushing=!1;pending=new Set;listeners=new Set;rootScope;observer;onError;constructor(e){this.observer=e?.observer,this.onError=e?.onError??(e=>{queueMicrotask(()=>{throw e})}),this.rootScope=new s(this,`runtime`),this.activeScope=this.rootScope}get disposed(){return this.isDisposed}signal=(e,t)=>(this.assertActive(),new a(this,e,t));computed=(e,t)=>{this.assertActive();let n=new o(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n};effect=(e,t)=>{this.assertActive();let n=new c(this,e,t);return(this.activeEffectScope??this.activeScope).owned.add(n),n.run(),n};createScope=e=>{this.assertActive();let t=new s(this,e);return this.activeScope.owned.add(t),t};batch=e=>(this.assertActive(),this.propagate(e));untrack=e=>(this.assertActive(),this.withObserver(void 0,e));dispose(){this.isDisposed||(this.isDisposed=!0,this.rootScope.dispose())}assertActive(){if(this.isDisposed)throw new e.RippleDisposedRuntimeError(`Cannot use a disposed Ripple runtime.`)}track(e){let t=this.activeObserver;t?.collecting!==void 0&&t.collecting.add(e)}clearDependencies(e){for(let t of e.dependencies)t.dependents.delete(e);e.dependencies.clear()}collect(e,t){return this.collectWith(e,t,e.dependencies.size===0)}collectEffect(e,t){return this.collectWith(e,t,!0)}withEffectScope(e,t){let n=this.activeEffectScope;this.activeEffectScope=e;try{return t()}finally{this.activeEffectScope=n}}withObserver(e,t){let n=this.activeObserver;this.activeObserver=e;try{return t()}finally{this.activeObserver=n}}withScope(e,t){let n=this.activeEffectScope,r=this.activeScope;this.activeEffectScope=void 0,this.activeScope=e;try{return t()}finally{this.activeEffectScope=n,this.activeScope=r}}enqueue(e){this.pending.add(e),this.flushDepth===0&&this.flush()}enqueueListener(e){this.listeners.add(e),this.flushDepth===0&&this.flush()}propagate(e){this.flushDepth++;try{return e()}finally{this.flushDepth--,this.flushDepth===0&&this.flush()}}emit(e){try{this.observer?.(e)}catch(t){this.report(t,{kind:`observer`,name:e.name})}}report(e,t){try{this.onError(e,t)}catch(e){queueMicrotask(()=>{throw e})}}collectWith(e,t,n){let r=this.activeObserver,i=new Set;e.collecting=i,this.activeObserver=e;try{let n=t();return this.commitDependencies(e,i),n}catch(t){throw n&&this.commitDependencies(e,i),t}finally{e.collecting=void 0,this.activeObserver=r}}commitDependencies(e,t){for(let n of e.dependencies)t.has(n)||n.dependents.delete(e);for(let n of t)e.dependencies.has(n)||n.dependents.add(e);e.dependencies.clear();for(let n of t)e.dependencies.add(n)}flush(){if(this.flushing)return;this.flushing=!0;let t=0;try{for(;this.pending.size>0||this.listeners.size>0;){if(++t>n)throw new e.RippleInfiniteLoopError(`infinite reactive flush (>${n} iterations)`);let r=[...this.pending],i=[...this.listeners];this.pending.clear(),this.listeners.clear();for(let e of r)e.run();for(let e of i)try{e()}catch(e){this.report(e,{kind:`listener`})}}}finally{this.flushing=!1}}},u=e=>{if(typeof e!=`object`||!e||!(t in e))return!1;let n=e;return typeof n.peek==`function`&&typeof n.subscribe==`function`};exports.REACTIVE=t,exports.ReactiveRuntime=l,exports.isReactive=u;
|
|
2
2
|
//# sourceMappingURL=runtime.cjs.map
|
package/dist/runtime.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.cjs","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["import {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleInfiniteLoopError,\n} from './errors';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n ReactiveErrorContext,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nexport const REACTIVE = Symbol.for('@vielzeug/ripple/reactive');\nconst MAX_FLUSH_ITERATIONS = 100;\nconst UNSET = Symbol('ripple.unset');\n\ntype Dependency = ReactiveNode<unknown>;\n\ntype ObserverNode = {\n collecting?: Set<Dependency>;\n readonly dependencies: Set<Dependency>;\n onDependencyChanged(): void;\n};\n\ntype Owned = {\n dispose(): void;\n};\n\nabstract class ReactiveNode<T> {\n readonly [REACTIVE] = true;\n readonly dependents = new Set<ObserverNode>();\n readonly name: string | undefined;\n protected readonly runtime: ReactiveRuntime;\n\n protected constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n abstract peek(): T;\n abstract get value(): T;\n\n subscribe(listener: () => void): Unsubscribe {\n this.runtime.assertActive();\n this.peek();\n\n const observer: ObserverNode = {\n dependencies: new Set(),\n onDependencyChanged: () => this.runtime.enqueueListener(listener),\n };\n\n this.dependents.add(observer);\n\n return () => this.dependents.delete(observer);\n }\n\n protected notify(): void {\n for (const dependent of [...this.dependents]) dependent.onDependencyChanged();\n }\n}\n\nclass SignalNode<T> extends ReactiveNode<T> implements Signal<T> {\n private current: T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, initial: T, options?: SignalOptions<T>) {\n super(runtime, options?.name);\n this.current = initial;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.runtime.track(this);\n\n return this.current;\n }\n\n set value(next: T) {\n this.runtime.assertActive();\n\n if (this.equals(this.current, next)) return;\n\n const previous = this.current;\n\n this.current = next;\n this.runtime.emit({ kind: 'write', name: this.name, next, previous });\n this.runtime.propagate(() => this.notify());\n }\n\n peek(): T {\n return this.current;\n }\n\n update(updater: (prev: T) => T): void {\n this.value = updater(this.current);\n }\n}\n\nclass ComputedNode<T> extends ReactiveNode<T> implements ObserverNode, Owned {\n readonly dependencies = new Set<Dependency>();\n private computing = false;\n private disposed = false;\n private dirty = true;\n private current: T | typeof UNSET = UNSET;\n private readonly derive: () => T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, derive: () => T, options?: ComputedOptions<T>) {\n super(runtime, options?.name);\n this.derive = derive;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.refresh();\n this.runtime.track(this);\n\n return this.current as T;\n }\n\n peek(): T {\n this.refresh();\n\n return this.current as T;\n }\n\n onDependencyChanged(): void {\n if (this.disposed) return;\n\n if (!this.dirty) this.dirty = true;\n\n if (this.dependents.size > 0 && this.refresh()) this.notify();\n }\n\n dispose(): void {\n if (this.disposed) return;\n\n this.disposed = true;\n this.runtime.clearDependencies(this);\n this.dependents.clear();\n }\n\n private refresh(): boolean {\n if (!this.dirty || this.disposed) return false;\n\n if (this.computing) {\n const label = this.name === undefined ? '' : ` \"${this.name}\"`;\n\n throw new RippleComputedCycleError(`computed cycle detected${label}`);\n }\n\n this.computing = true;\n this.runtime.emit({ kind: 'compute', name: this.name });\n\n try {\n const next = this.runtime.collect(this, this.derive);\n const changed = this.current === UNSET || !this.equals(this.current as T, next);\n\n this.current = next;\n this.dirty = false;\n\n return changed;\n } finally {\n this.computing = false;\n }\n }\n}\n\nclass ScopeNode implements Scope {\n readonly disposalController = new AbortController();\n readonly owned = new Set<Owned>();\n readonly name: string | undefined;\n private isDisposed = false;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n run<T>(fn: () => T): T {\n if (this.isDisposed) throw new RippleDisposedScopeError('Cannot run a disposed scope.');\n\n return this.runtime.withScope(this, fn);\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n for (const owned of [...this.owned].reverse()) owned.dispose();\n this.owned.clear();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.name, node: 'scope' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nclass EffectNode implements ObserverNode, EffectHandle {\n readonly dependencies = new Set<Dependency>();\n readonly disposalController = new AbortController();\n private cleanup: Cleanup | undefined;\n private isDisposed = false;\n private owner: ScopeNode | undefined;\n private scheduled = false;\n private readonly callback: () => Cleanup | undefined;\n private readonly options: EffectOptions | undefined;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, callback: () => Cleanup | undefined, options?: EffectOptions) {\n this.runtime = runtime;\n this.callback = callback;\n this.options = options;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n onDependencyChanged(): void {\n if (this.isDisposed) return;\n\n if (this.options?.scheduler === 'microtask') {\n if (this.scheduled) return;\n\n this.scheduled = true;\n queueMicrotask(() => {\n this.scheduled = false;\n\n if (!this.isDisposed) this.runtime.enqueue(this);\n });\n\n return;\n }\n\n this.runtime.enqueue(this);\n }\n\n run(): void {\n if (this.isDisposed) return;\n\n this.owner?.dispose();\n this.owner = undefined;\n this.runCleanup();\n this.runtime.emit({ kind: 'effect', name: this.options?.name });\n\n const owner = new ScopeNode(this.runtime);\n\n try {\n const cleanup = this.runtime.withEffectScope(owner, () => this.runtime.collectEffect(this, this.callback));\n\n this.owner = owner;\n this.cleanup = typeof cleanup === 'function' ? cleanup : undefined;\n } catch (error) {\n owner.dispose();\n this.runtime.report(error, { kind: 'effect', name: this.options?.name });\n }\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.owner?.dispose();\n this.owner = undefined;\n this.runtime.clearDependencies(this);\n this.runCleanup();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.options?.name, node: 'effect' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n private runCleanup(): void {\n const cleanup = this.cleanup;\n\n this.cleanup = undefined;\n\n if (cleanup === undefined) return;\n\n try {\n cleanup();\n } catch (error) {\n this.runtime.report(error, { kind: 'cleanup', name: this.options?.name });\n }\n }\n}\n\n/**\n * A runtime owns reactive graph state and lifetime. Separate instances isolate\n * applications and SSR requests without process-wide mutable hooks.\n */\nexport class ReactiveRuntime {\n private activeEffectScope: ScopeNode | undefined;\n private activeObserver: ObserverNode | undefined;\n private activeScope: ScopeNode;\n private isDisposed = false;\n private flushDepth = 0;\n private flushing = false;\n private readonly pending = new Set<EffectNode>();\n private readonly listeners = new Set<() => void>();\n private readonly rootScope: ScopeNode;\n private readonly observer: ReactiveObserver | undefined;\n private readonly onError: (error: unknown, context: ReactiveErrorContext) => void;\n\n constructor(options?: RippleOptions) {\n this.observer = options?.observer;\n this.onError =\n options?.onError ??\n ((error) => {\n queueMicrotask(() => {\n throw error;\n });\n });\n this.rootScope = new ScopeNode(this, 'runtime');\n this.activeScope = this.rootScope;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n readonly signal = <T>(initial: T, options?: SignalOptions<T>): Signal<T> => {\n this.assertActive();\n\n return new SignalNode(this, initial, options);\n };\n\n readonly computed = <T>(derive: () => T, options?: ComputedOptions<T>): Readable<T> => {\n this.assertActive();\n\n const node = new ComputedNode(this, derive, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n\n return node;\n };\n\n readonly effect = (callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle => {\n this.assertActive();\n\n const node = new EffectNode(this, callback, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n node.run();\n\n return node;\n };\n\n readonly createScope = (name?: string): Scope => {\n this.assertActive();\n\n const scope = new ScopeNode(this, name);\n\n // Scopes model explicit, caller-owned lifetimes. Unlike effects/computeds created during an\n // effect run, they deliberately attach to the enclosing scope rather than the per-run owner:\n // keyed DOM directives retain item scopes across reconciliation runs and dispose them only\n // when the item itself leaves the collection.\n this.activeScope.owned.add(scope);\n\n return scope;\n };\n\n readonly batch = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.propagate(fn);\n };\n\n readonly untrack = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.withObserver(undefined, fn);\n };\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.rootScope.dispose();\n }\n\n /** Internal node guard: disposed runtimes allow inert reads but reject graph work and mutation. */\n assertActive(): void {\n if (this.isDisposed) throw new RippleDisposedRuntimeError('Cannot use a disposed Ripple runtime.');\n }\n\n track(node: Dependency): void {\n const observer = this.activeObserver;\n\n if (observer?.collecting === undefined) return;\n\n observer.collecting.add(node);\n }\n\n clearDependencies(observer: ObserverNode): void {\n for (const dependency of observer.dependencies) dependency.dependents.delete(observer);\n observer.dependencies.clear();\n }\n\n collect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, false);\n }\n\n collectEffect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, true);\n }\n\n withEffectScope<T>(scope: ScopeNode, fn: () => T): T {\n const previous = this.activeEffectScope;\n\n this.activeEffectScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previous;\n }\n }\n\n withObserver<T>(observer: ObserverNode | undefined, fn: () => T): T {\n const previous = this.activeObserver;\n\n this.activeObserver = observer;\n\n try {\n return fn();\n } finally {\n this.activeObserver = previous;\n }\n }\n\n withScope<T>(scope: ScopeNode, fn: () => T): T {\n const previousEffectScope = this.activeEffectScope;\n const previousScope = this.activeScope;\n\n this.activeEffectScope = undefined;\n this.activeScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previousEffectScope;\n this.activeScope = previousScope;\n }\n }\n\n enqueue(effect: EffectNode): void {\n this.pending.add(effect);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n enqueueListener(listener: () => void): void {\n this.listeners.add(listener);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n propagate<T>(fn: () => T): T {\n this.flushDepth++;\n\n try {\n return fn();\n } finally {\n this.flushDepth--;\n\n if (this.flushDepth === 0) this.flush();\n }\n }\n\n emit(event: Parameters<ReactiveObserver>[0]): void {\n try {\n this.observer?.(event);\n } catch (error) {\n this.report(error, { kind: 'observer', name: event.name });\n }\n }\n\n report(error: unknown, context: ReactiveErrorContext): void {\n try {\n this.onError(error, context);\n } catch (reporterError) {\n queueMicrotask(() => {\n throw reporterError;\n });\n }\n }\n\n private collectWith<T>(observer: ObserverNode, fn: () => T, commitOnError: boolean): T {\n const previousObserver = this.activeObserver;\n const dependencies = new Set<Dependency>();\n\n observer.collecting = dependencies;\n this.activeObserver = observer;\n\n try {\n const result = fn();\n\n this.commitDependencies(observer, dependencies);\n\n return result;\n } catch (error) {\n if (commitOnError) this.commitDependencies(observer, dependencies);\n\n throw error;\n } finally {\n observer.collecting = undefined;\n this.activeObserver = previousObserver;\n }\n }\n\n private commitDependencies(observer: ObserverNode, next: Set<Dependency>): void {\n for (const dependency of observer.dependencies) {\n if (!next.has(dependency)) dependency.dependents.delete(observer);\n }\n\n for (const dependency of next) {\n if (!observer.dependencies.has(dependency)) dependency.dependents.add(observer);\n }\n\n observer.dependencies.clear();\n for (const dependency of next) observer.dependencies.add(dependency);\n }\n\n private flush(): void {\n if (this.flushing) return;\n\n this.flushing = true;\n\n let iterations = 0;\n\n try {\n while (this.pending.size > 0 || this.listeners.size > 0) {\n if (++iterations > MAX_FLUSH_ITERATIONS) {\n throw new RippleInfiniteLoopError(`infinite reactive flush (>${MAX_FLUSH_ITERATIONS} iterations)`);\n }\n\n const effects = [...this.pending];\n const listeners = [...this.listeners];\n\n this.pending.clear();\n this.listeners.clear();\n\n for (const effect of effects) effect.run();\n\n for (const listener of listeners) {\n try {\n listener();\n } catch (error) {\n this.report(error, { kind: 'listener' });\n }\n }\n }\n } finally {\n this.flushing = false;\n }\n }\n}\n\nexport const isReactive = <T>(value: T | Readable<T>): value is Readable<T> => {\n if (typeof value !== 'object' || value === null || !(REACTIVE in value)) return false;\n\n const candidate = value as { peek?: unknown; subscribe?: unknown };\n\n return typeof candidate.peek === 'function' && typeof candidate.subscribe === 'function';\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.cjs","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["import {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleInfiniteLoopError,\n} from './errors';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n ReactiveErrorContext,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nexport const REACTIVE = Symbol.for('@vielzeug/ripple/reactive');\nconst MAX_FLUSH_ITERATIONS = 100;\nconst UNSET = Symbol('ripple.unset');\n\ntype Dependency = ReactiveNode<unknown>;\n\ntype ObserverNode = {\n collecting?: Set<Dependency>;\n readonly dependencies: Set<Dependency>;\n onDependencyChanged(): void;\n};\n\ntype Owned = {\n dispose(): void;\n};\n\nabstract class ReactiveNode<T> {\n readonly [REACTIVE] = true;\n readonly dependents = new Set<ObserverNode>();\n readonly name: string | undefined;\n protected readonly runtime: ReactiveRuntime;\n\n protected constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n abstract peek(): T;\n abstract get value(): T;\n\n subscribe(listener: () => void): Unsubscribe {\n this.runtime.assertActive();\n this.peek();\n\n const observer: ObserverNode = {\n dependencies: new Set(),\n onDependencyChanged: () => this.runtime.enqueueListener(listener),\n };\n\n this.dependents.add(observer);\n\n return () => this.dependents.delete(observer);\n }\n\n protected notify(): void {\n for (const dependent of [...this.dependents]) dependent.onDependencyChanged();\n }\n}\n\nclass SignalNode<T> extends ReactiveNode<T> implements Signal<T> {\n private current: T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, initial: T, options?: SignalOptions<T>) {\n super(runtime, options?.name);\n this.current = initial;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.runtime.track(this);\n\n return this.current;\n }\n\n set value(next: T) {\n this.runtime.assertActive();\n\n if (this.equals(this.current, next)) return;\n\n const previous = this.current;\n\n this.current = next;\n this.runtime.emit({ kind: 'write', name: this.name, next, previous });\n this.runtime.propagate(() => this.notify());\n }\n\n peek(): T {\n return this.current;\n }\n\n update(updater: (prev: T) => T): void {\n this.value = updater(this.current);\n }\n}\n\nclass ComputedNode<T> extends ReactiveNode<T> implements ObserverNode, Owned {\n readonly dependencies = new Set<Dependency>();\n private computing = false;\n private disposed = false;\n private dirty = true;\n private current: T | typeof UNSET = UNSET;\n private readonly derive: () => T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, derive: () => T, options?: ComputedOptions<T>) {\n super(runtime, options?.name);\n this.derive = derive;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n // Track before refresh: if refresh throws, the consumer still depends on\n // this computed and must be notified when a dependency change might let it\n // succeed. Without this, a first-run failure permanently severs the\n // consumer from the computed.\n this.runtime.track(this);\n this.refresh();\n\n return this.current as T;\n }\n\n peek(): T {\n this.refresh();\n\n return this.current as T;\n }\n\n onDependencyChanged(): void {\n if (this.disposed) return;\n\n if (!this.dirty) this.dirty = true;\n\n if (this.dependents.size > 0 && this.refresh()) this.notify();\n }\n\n dispose(): void {\n if (this.disposed) return;\n\n this.disposed = true;\n this.runtime.clearDependencies(this);\n this.dependents.clear();\n }\n\n private refresh(): boolean {\n if (!this.dirty || this.disposed) return false;\n\n if (this.computing) {\n const label = this.name === undefined ? '' : ` \"${this.name}\"`;\n\n throw new RippleComputedCycleError(`computed cycle detected${label}`);\n }\n\n this.computing = true;\n this.runtime.emit({ kind: 'compute', name: this.name });\n\n try {\n const next = this.runtime.collect(this, this.derive);\n const changed = this.current === UNSET || !this.equals(this.current as T, next);\n\n this.current = next;\n this.dirty = false;\n\n return changed;\n } finally {\n this.computing = false;\n }\n }\n}\n\nclass ScopeNode implements Scope {\n readonly disposalController = new AbortController();\n readonly owned = new Set<Owned>();\n readonly name: string | undefined;\n private isDisposed = false;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n run<T>(fn: () => T): T {\n if (this.isDisposed) throw new RippleDisposedScopeError('Cannot run a disposed scope.');\n\n return this.runtime.withScope(this, fn);\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n for (const owned of [...this.owned].reverse()) owned.dispose();\n this.owned.clear();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.name, node: 'scope' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nclass EffectNode implements ObserverNode, EffectHandle {\n readonly dependencies = new Set<Dependency>();\n readonly disposalController = new AbortController();\n private cleanup: Cleanup | undefined;\n private isDisposed = false;\n private owner: ScopeNode | undefined;\n private scheduled = false;\n private readonly callback: () => Cleanup | undefined;\n private readonly options: EffectOptions | undefined;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, callback: () => Cleanup | undefined, options?: EffectOptions) {\n this.runtime = runtime;\n this.callback = callback;\n this.options = options;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n onDependencyChanged(): void {\n if (this.isDisposed) return;\n\n if (this.options?.scheduler === 'microtask') {\n if (this.scheduled) return;\n\n this.scheduled = true;\n queueMicrotask(() => {\n this.scheduled = false;\n\n if (!this.isDisposed) this.runtime.enqueue(this);\n });\n\n return;\n }\n\n this.runtime.enqueue(this);\n }\n\n run(): void {\n if (this.isDisposed) return;\n\n this.owner?.dispose();\n this.owner = undefined;\n this.runCleanup();\n this.runtime.emit({ kind: 'effect', name: this.options?.name });\n\n const owner = new ScopeNode(this.runtime);\n\n try {\n const cleanup = this.runtime.withEffectScope(owner, () => this.runtime.collectEffect(this, this.callback));\n\n this.owner = owner;\n this.cleanup = typeof cleanup === 'function' ? cleanup : undefined;\n } catch (error) {\n owner.dispose();\n this.runtime.report(error, { kind: 'effect', name: this.options?.name });\n }\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.owner?.dispose();\n this.owner = undefined;\n this.runtime.clearDependencies(this);\n this.runCleanup();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.options?.name, node: 'effect' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n private runCleanup(): void {\n const cleanup = this.cleanup;\n\n this.cleanup = undefined;\n\n if (cleanup === undefined) return;\n\n try {\n cleanup();\n } catch (error) {\n this.runtime.report(error, { kind: 'cleanup', name: this.options?.name });\n }\n }\n}\n\n/**\n * A runtime owns reactive graph state and lifetime. Separate instances isolate\n * applications and SSR requests without process-wide mutable hooks.\n */\nexport class ReactiveRuntime {\n private activeEffectScope: ScopeNode | undefined;\n private activeObserver: ObserverNode | undefined;\n private activeScope: ScopeNode;\n private isDisposed = false;\n private flushDepth = 0;\n private flushing = false;\n private readonly pending = new Set<EffectNode>();\n private readonly listeners = new Set<() => void>();\n private readonly rootScope: ScopeNode;\n private readonly observer: ReactiveObserver | undefined;\n private readonly onError: (error: unknown, context: ReactiveErrorContext) => void;\n\n constructor(options?: RippleOptions) {\n this.observer = options?.observer;\n this.onError =\n options?.onError ??\n ((error) => {\n queueMicrotask(() => {\n throw error;\n });\n });\n this.rootScope = new ScopeNode(this, 'runtime');\n this.activeScope = this.rootScope;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n readonly signal = <T>(initial: T, options?: SignalOptions<T>): Signal<T> => {\n this.assertActive();\n\n return new SignalNode(this, initial, options);\n };\n\n readonly computed = <T>(derive: () => T, options?: ComputedOptions<T>): Readable<T> => {\n this.assertActive();\n\n const node = new ComputedNode(this, derive, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n\n return node;\n };\n\n readonly effect = (callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle => {\n this.assertActive();\n\n const node = new EffectNode(this, callback, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n node.run();\n\n return node;\n };\n\n readonly createScope = (name?: string): Scope => {\n this.assertActive();\n\n const scope = new ScopeNode(this, name);\n\n // Scopes model explicit, caller-owned lifetimes. Unlike effects/computeds created during an\n // effect run, they deliberately attach to the enclosing scope rather than the per-run owner:\n // keyed DOM directives retain item scopes across reconciliation runs and dispose them only\n // when the item itself leaves the collection.\n this.activeScope.owned.add(scope);\n\n return scope;\n };\n\n readonly batch = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.propagate(fn);\n };\n\n readonly untrack = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.withObserver(undefined, fn);\n };\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.rootScope.dispose();\n }\n\n /** Internal node guard: disposed runtimes allow inert reads but reject graph work and mutation. */\n assertActive(): void {\n if (this.isDisposed) throw new RippleDisposedRuntimeError('Cannot use a disposed Ripple runtime.');\n }\n\n track(node: Dependency): void {\n const observer = this.activeObserver;\n\n if (observer?.collecting === undefined) return;\n\n observer.collecting.add(node);\n }\n\n clearDependencies(observer: ObserverNode): void {\n for (const dependency of observer.dependencies) dependency.dependents.delete(observer);\n observer.dependencies.clear();\n }\n\n collect<T>(observer: ObserverNode, fn: () => T): T {\n // On first run (no prior dependencies), commit partial dependencies even if\n // derive throws — otherwise the computed would have zero dependencies and never\n // be notified when its source changes, permanently stuck until a manual read.\n // On subsequent runs, keep previous dependencies (tested behavior).\n return this.collectWith(observer, fn, observer.dependencies.size === 0);\n }\n\n collectEffect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, true);\n }\n\n withEffectScope<T>(scope: ScopeNode, fn: () => T): T {\n const previous = this.activeEffectScope;\n\n this.activeEffectScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previous;\n }\n }\n\n withObserver<T>(observer: ObserverNode | undefined, fn: () => T): T {\n const previous = this.activeObserver;\n\n this.activeObserver = observer;\n\n try {\n return fn();\n } finally {\n this.activeObserver = previous;\n }\n }\n\n withScope<T>(scope: ScopeNode, fn: () => T): T {\n const previousEffectScope = this.activeEffectScope;\n const previousScope = this.activeScope;\n\n this.activeEffectScope = undefined;\n this.activeScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previousEffectScope;\n this.activeScope = previousScope;\n }\n }\n\n enqueue(effect: EffectNode): void {\n this.pending.add(effect);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n enqueueListener(listener: () => void): void {\n this.listeners.add(listener);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n propagate<T>(fn: () => T): T {\n this.flushDepth++;\n\n try {\n return fn();\n } finally {\n this.flushDepth--;\n\n if (this.flushDepth === 0) this.flush();\n }\n }\n\n emit(event: Parameters<ReactiveObserver>[0]): void {\n try {\n this.observer?.(event);\n } catch (error) {\n this.report(error, { kind: 'observer', name: event.name });\n }\n }\n\n report(error: unknown, context: ReactiveErrorContext): void {\n try {\n this.onError(error, context);\n } catch (reporterError) {\n queueMicrotask(() => {\n throw reporterError;\n });\n }\n }\n\n private collectWith<T>(observer: ObserverNode, fn: () => T, commitOnError: boolean): T {\n const previousObserver = this.activeObserver;\n const dependencies = new Set<Dependency>();\n\n observer.collecting = dependencies;\n this.activeObserver = observer;\n\n try {\n const result = fn();\n\n this.commitDependencies(observer, dependencies);\n\n return result;\n } catch (error) {\n if (commitOnError) this.commitDependencies(observer, dependencies);\n\n throw error;\n } finally {\n observer.collecting = undefined;\n this.activeObserver = previousObserver;\n }\n }\n\n private commitDependencies(observer: ObserverNode, next: Set<Dependency>): void {\n for (const dependency of observer.dependencies) {\n if (!next.has(dependency)) dependency.dependents.delete(observer);\n }\n\n for (const dependency of next) {\n if (!observer.dependencies.has(dependency)) dependency.dependents.add(observer);\n }\n\n observer.dependencies.clear();\n for (const dependency of next) observer.dependencies.add(dependency);\n }\n\n private flush(): void {\n if (this.flushing) return;\n\n this.flushing = true;\n\n let iterations = 0;\n\n try {\n while (this.pending.size > 0 || this.listeners.size > 0) {\n if (++iterations > MAX_FLUSH_ITERATIONS) {\n throw new RippleInfiniteLoopError(`infinite reactive flush (>${MAX_FLUSH_ITERATIONS} iterations)`);\n }\n\n const effects = [...this.pending];\n const listeners = [...this.listeners];\n\n this.pending.clear();\n this.listeners.clear();\n\n for (const effect of effects) effect.run();\n\n for (const listener of listeners) {\n try {\n listener();\n } catch (error) {\n this.report(error, { kind: 'listener' });\n }\n }\n }\n } finally {\n this.flushing = false;\n }\n }\n}\n\nexport const isReactive = <T>(value: T | Readable<T>): value is Readable<T> => {\n if (typeof value !== 'object' || value === null || !(REACTIVE in value)) return false;\n\n const candidate = value as { peek?: unknown; subscribe?: unknown };\n\n return typeof candidate.peek === 'function' && typeof candidate.subscribe === 'function';\n};\n"],"mappings":"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"}
|
package/dist/runtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,OAAO,EACP,eAAe,EACf,YAAY,EACZ,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,QAAQ,EACR,aAAa,EACb,KAAK,EACL,MAAM,EACN,aAAa,EACb,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,QAAQ,eAA0C,CAAC;AAIhE,KAAK,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;AAExC,KAAK,YAAY,GAAG;IAClB,UAAU,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACvC,mBAAmB,IAAI,IAAI,CAAC;CAC7B,CAAC;AAEF,KAAK,KAAK,GAAG;IACX,OAAO,IAAI,IAAI,CAAC;CACjB,CAAC;AAEF,uBAAe,YAAY,CAAC,CAAC;IAC3B,QAAQ,CAAC,CAAC,QAAQ,CAAC,QAAQ;IAC3B,QAAQ,CAAC,UAAU,oBAA2B;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAE5C,SAAS,aAAa,OAAO,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,MAAM;IAK7D,QAAQ,CAAC,IAAI,IAAI,CAAC;IAClB,QAAQ,KAAK,KAAK,IAAI,CAAC,CAAC;IAExB,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,WAAW;IAc5C,SAAS,CAAC,MAAM,IAAI,IAAI;CAGzB;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/runtime.js
CHANGED
|
@@ -56,7 +56,7 @@ var i = Symbol.for("@vielzeug/ripple/reactive"), a = 100, o = Symbol("ripple.uns
|
|
|
56
56
|
super(e, n?.name), this.derive = t, this.equals = n?.equals ?? Object.is;
|
|
57
57
|
}
|
|
58
58
|
get value() {
|
|
59
|
-
return this.
|
|
59
|
+
return this.runtime.track(this), this.refresh(), this.current;
|
|
60
60
|
}
|
|
61
61
|
peek() {
|
|
62
62
|
return this.refresh(), this.current;
|
|
@@ -241,7 +241,7 @@ var i = Symbol.for("@vielzeug/ripple/reactive"), a = 100, o = Symbol("ripple.uns
|
|
|
241
241
|
e.dependencies.clear();
|
|
242
242
|
}
|
|
243
243
|
collect(e, t) {
|
|
244
|
-
return this.collectWith(e, t,
|
|
244
|
+
return this.collectWith(e, t, e.dependencies.size === 0);
|
|
245
245
|
}
|
|
246
246
|
collectEffect(e, t) {
|
|
247
247
|
return this.collectWith(e, t, !0);
|
package/dist/runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["import {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleInfiniteLoopError,\n} from './errors';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n ReactiveErrorContext,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nexport const REACTIVE = Symbol.for('@vielzeug/ripple/reactive');\nconst MAX_FLUSH_ITERATIONS = 100;\nconst UNSET = Symbol('ripple.unset');\n\ntype Dependency = ReactiveNode<unknown>;\n\ntype ObserverNode = {\n collecting?: Set<Dependency>;\n readonly dependencies: Set<Dependency>;\n onDependencyChanged(): void;\n};\n\ntype Owned = {\n dispose(): void;\n};\n\nabstract class ReactiveNode<T> {\n readonly [REACTIVE] = true;\n readonly dependents = new Set<ObserverNode>();\n readonly name: string | undefined;\n protected readonly runtime: ReactiveRuntime;\n\n protected constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n abstract peek(): T;\n abstract get value(): T;\n\n subscribe(listener: () => void): Unsubscribe {\n this.runtime.assertActive();\n this.peek();\n\n const observer: ObserverNode = {\n dependencies: new Set(),\n onDependencyChanged: () => this.runtime.enqueueListener(listener),\n };\n\n this.dependents.add(observer);\n\n return () => this.dependents.delete(observer);\n }\n\n protected notify(): void {\n for (const dependent of [...this.dependents]) dependent.onDependencyChanged();\n }\n}\n\nclass SignalNode<T> extends ReactiveNode<T> implements Signal<T> {\n private current: T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, initial: T, options?: SignalOptions<T>) {\n super(runtime, options?.name);\n this.current = initial;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.runtime.track(this);\n\n return this.current;\n }\n\n set value(next: T) {\n this.runtime.assertActive();\n\n if (this.equals(this.current, next)) return;\n\n const previous = this.current;\n\n this.current = next;\n this.runtime.emit({ kind: 'write', name: this.name, next, previous });\n this.runtime.propagate(() => this.notify());\n }\n\n peek(): T {\n return this.current;\n }\n\n update(updater: (prev: T) => T): void {\n this.value = updater(this.current);\n }\n}\n\nclass ComputedNode<T> extends ReactiveNode<T> implements ObserverNode, Owned {\n readonly dependencies = new Set<Dependency>();\n private computing = false;\n private disposed = false;\n private dirty = true;\n private current: T | typeof UNSET = UNSET;\n private readonly derive: () => T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, derive: () => T, options?: ComputedOptions<T>) {\n super(runtime, options?.name);\n this.derive = derive;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.refresh();\n this.runtime.track(this);\n\n return this.current as T;\n }\n\n peek(): T {\n this.refresh();\n\n return this.current as T;\n }\n\n onDependencyChanged(): void {\n if (this.disposed) return;\n\n if (!this.dirty) this.dirty = true;\n\n if (this.dependents.size > 0 && this.refresh()) this.notify();\n }\n\n dispose(): void {\n if (this.disposed) return;\n\n this.disposed = true;\n this.runtime.clearDependencies(this);\n this.dependents.clear();\n }\n\n private refresh(): boolean {\n if (!this.dirty || this.disposed) return false;\n\n if (this.computing) {\n const label = this.name === undefined ? '' : ` \"${this.name}\"`;\n\n throw new RippleComputedCycleError(`computed cycle detected${label}`);\n }\n\n this.computing = true;\n this.runtime.emit({ kind: 'compute', name: this.name });\n\n try {\n const next = this.runtime.collect(this, this.derive);\n const changed = this.current === UNSET || !this.equals(this.current as T, next);\n\n this.current = next;\n this.dirty = false;\n\n return changed;\n } finally {\n this.computing = false;\n }\n }\n}\n\nclass ScopeNode implements Scope {\n readonly disposalController = new AbortController();\n readonly owned = new Set<Owned>();\n readonly name: string | undefined;\n private isDisposed = false;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n run<T>(fn: () => T): T {\n if (this.isDisposed) throw new RippleDisposedScopeError('Cannot run a disposed scope.');\n\n return this.runtime.withScope(this, fn);\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n for (const owned of [...this.owned].reverse()) owned.dispose();\n this.owned.clear();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.name, node: 'scope' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nclass EffectNode implements ObserverNode, EffectHandle {\n readonly dependencies = new Set<Dependency>();\n readonly disposalController = new AbortController();\n private cleanup: Cleanup | undefined;\n private isDisposed = false;\n private owner: ScopeNode | undefined;\n private scheduled = false;\n private readonly callback: () => Cleanup | undefined;\n private readonly options: EffectOptions | undefined;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, callback: () => Cleanup | undefined, options?: EffectOptions) {\n this.runtime = runtime;\n this.callback = callback;\n this.options = options;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n onDependencyChanged(): void {\n if (this.isDisposed) return;\n\n if (this.options?.scheduler === 'microtask') {\n if (this.scheduled) return;\n\n this.scheduled = true;\n queueMicrotask(() => {\n this.scheduled = false;\n\n if (!this.isDisposed) this.runtime.enqueue(this);\n });\n\n return;\n }\n\n this.runtime.enqueue(this);\n }\n\n run(): void {\n if (this.isDisposed) return;\n\n this.owner?.dispose();\n this.owner = undefined;\n this.runCleanup();\n this.runtime.emit({ kind: 'effect', name: this.options?.name });\n\n const owner = new ScopeNode(this.runtime);\n\n try {\n const cleanup = this.runtime.withEffectScope(owner, () => this.runtime.collectEffect(this, this.callback));\n\n this.owner = owner;\n this.cleanup = typeof cleanup === 'function' ? cleanup : undefined;\n } catch (error) {\n owner.dispose();\n this.runtime.report(error, { kind: 'effect', name: this.options?.name });\n }\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.owner?.dispose();\n this.owner = undefined;\n this.runtime.clearDependencies(this);\n this.runCleanup();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.options?.name, node: 'effect' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n private runCleanup(): void {\n const cleanup = this.cleanup;\n\n this.cleanup = undefined;\n\n if (cleanup === undefined) return;\n\n try {\n cleanup();\n } catch (error) {\n this.runtime.report(error, { kind: 'cleanup', name: this.options?.name });\n }\n }\n}\n\n/**\n * A runtime owns reactive graph state and lifetime. Separate instances isolate\n * applications and SSR requests without process-wide mutable hooks.\n */\nexport class ReactiveRuntime {\n private activeEffectScope: ScopeNode | undefined;\n private activeObserver: ObserverNode | undefined;\n private activeScope: ScopeNode;\n private isDisposed = false;\n private flushDepth = 0;\n private flushing = false;\n private readonly pending = new Set<EffectNode>();\n private readonly listeners = new Set<() => void>();\n private readonly rootScope: ScopeNode;\n private readonly observer: ReactiveObserver | undefined;\n private readonly onError: (error: unknown, context: ReactiveErrorContext) => void;\n\n constructor(options?: RippleOptions) {\n this.observer = options?.observer;\n this.onError =\n options?.onError ??\n ((error) => {\n queueMicrotask(() => {\n throw error;\n });\n });\n this.rootScope = new ScopeNode(this, 'runtime');\n this.activeScope = this.rootScope;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n readonly signal = <T>(initial: T, options?: SignalOptions<T>): Signal<T> => {\n this.assertActive();\n\n return new SignalNode(this, initial, options);\n };\n\n readonly computed = <T>(derive: () => T, options?: ComputedOptions<T>): Readable<T> => {\n this.assertActive();\n\n const node = new ComputedNode(this, derive, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n\n return node;\n };\n\n readonly effect = (callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle => {\n this.assertActive();\n\n const node = new EffectNode(this, callback, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n node.run();\n\n return node;\n };\n\n readonly createScope = (name?: string): Scope => {\n this.assertActive();\n\n const scope = new ScopeNode(this, name);\n\n // Scopes model explicit, caller-owned lifetimes. Unlike effects/computeds created during an\n // effect run, they deliberately attach to the enclosing scope rather than the per-run owner:\n // keyed DOM directives retain item scopes across reconciliation runs and dispose them only\n // when the item itself leaves the collection.\n this.activeScope.owned.add(scope);\n\n return scope;\n };\n\n readonly batch = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.propagate(fn);\n };\n\n readonly untrack = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.withObserver(undefined, fn);\n };\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.rootScope.dispose();\n }\n\n /** Internal node guard: disposed runtimes allow inert reads but reject graph work and mutation. */\n assertActive(): void {\n if (this.isDisposed) throw new RippleDisposedRuntimeError('Cannot use a disposed Ripple runtime.');\n }\n\n track(node: Dependency): void {\n const observer = this.activeObserver;\n\n if (observer?.collecting === undefined) return;\n\n observer.collecting.add(node);\n }\n\n clearDependencies(observer: ObserverNode): void {\n for (const dependency of observer.dependencies) dependency.dependents.delete(observer);\n observer.dependencies.clear();\n }\n\n collect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, false);\n }\n\n collectEffect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, true);\n }\n\n withEffectScope<T>(scope: ScopeNode, fn: () => T): T {\n const previous = this.activeEffectScope;\n\n this.activeEffectScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previous;\n }\n }\n\n withObserver<T>(observer: ObserverNode | undefined, fn: () => T): T {\n const previous = this.activeObserver;\n\n this.activeObserver = observer;\n\n try {\n return fn();\n } finally {\n this.activeObserver = previous;\n }\n }\n\n withScope<T>(scope: ScopeNode, fn: () => T): T {\n const previousEffectScope = this.activeEffectScope;\n const previousScope = this.activeScope;\n\n this.activeEffectScope = undefined;\n this.activeScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previousEffectScope;\n this.activeScope = previousScope;\n }\n }\n\n enqueue(effect: EffectNode): void {\n this.pending.add(effect);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n enqueueListener(listener: () => void): void {\n this.listeners.add(listener);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n propagate<T>(fn: () => T): T {\n this.flushDepth++;\n\n try {\n return fn();\n } finally {\n this.flushDepth--;\n\n if (this.flushDepth === 0) this.flush();\n }\n }\n\n emit(event: Parameters<ReactiveObserver>[0]): void {\n try {\n this.observer?.(event);\n } catch (error) {\n this.report(error, { kind: 'observer', name: event.name });\n }\n }\n\n report(error: unknown, context: ReactiveErrorContext): void {\n try {\n this.onError(error, context);\n } catch (reporterError) {\n queueMicrotask(() => {\n throw reporterError;\n });\n }\n }\n\n private collectWith<T>(observer: ObserverNode, fn: () => T, commitOnError: boolean): T {\n const previousObserver = this.activeObserver;\n const dependencies = new Set<Dependency>();\n\n observer.collecting = dependencies;\n this.activeObserver = observer;\n\n try {\n const result = fn();\n\n this.commitDependencies(observer, dependencies);\n\n return result;\n } catch (error) {\n if (commitOnError) this.commitDependencies(observer, dependencies);\n\n throw error;\n } finally {\n observer.collecting = undefined;\n this.activeObserver = previousObserver;\n }\n }\n\n private commitDependencies(observer: ObserverNode, next: Set<Dependency>): void {\n for (const dependency of observer.dependencies) {\n if (!next.has(dependency)) dependency.dependents.delete(observer);\n }\n\n for (const dependency of next) {\n if (!observer.dependencies.has(dependency)) dependency.dependents.add(observer);\n }\n\n observer.dependencies.clear();\n for (const dependency of next) observer.dependencies.add(dependency);\n }\n\n private flush(): void {\n if (this.flushing) return;\n\n this.flushing = true;\n\n let iterations = 0;\n\n try {\n while (this.pending.size > 0 || this.listeners.size > 0) {\n if (++iterations > MAX_FLUSH_ITERATIONS) {\n throw new RippleInfiniteLoopError(`infinite reactive flush (>${MAX_FLUSH_ITERATIONS} iterations)`);\n }\n\n const effects = [...this.pending];\n const listeners = [...this.listeners];\n\n this.pending.clear();\n this.listeners.clear();\n\n for (const effect of effects) effect.run();\n\n for (const listener of listeners) {\n try {\n listener();\n } catch (error) {\n this.report(error, { kind: 'listener' });\n }\n }\n }\n } finally {\n this.flushing = false;\n }\n }\n}\n\nexport const isReactive = <T>(value: T | Readable<T>): value is Readable<T> => {\n if (typeof value !== 'object' || value === null || !(REACTIVE in value)) return false;\n\n const candidate = value as { peek?: unknown; subscribe?: unknown };\n\n return typeof candidate.peek === 'function' && typeof candidate.subscribe === 'function';\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"runtime.js","names":[],"sources":["../src/runtime.ts"],"sourcesContent":["import {\n RippleComputedCycleError,\n RippleDisposedRuntimeError,\n RippleDisposedScopeError,\n RippleInfiniteLoopError,\n} from './errors';\nimport type {\n Cleanup,\n ComputedOptions,\n EffectHandle,\n EffectOptions,\n ReactiveErrorContext,\n ReactiveObserver,\n Readable,\n RippleOptions,\n Scope,\n Signal,\n SignalOptions,\n Unsubscribe,\n} from './types';\n\nexport const REACTIVE = Symbol.for('@vielzeug/ripple/reactive');\nconst MAX_FLUSH_ITERATIONS = 100;\nconst UNSET = Symbol('ripple.unset');\n\ntype Dependency = ReactiveNode<unknown>;\n\ntype ObserverNode = {\n collecting?: Set<Dependency>;\n readonly dependencies: Set<Dependency>;\n onDependencyChanged(): void;\n};\n\ntype Owned = {\n dispose(): void;\n};\n\nabstract class ReactiveNode<T> {\n readonly [REACTIVE] = true;\n readonly dependents = new Set<ObserverNode>();\n readonly name: string | undefined;\n protected readonly runtime: ReactiveRuntime;\n\n protected constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n abstract peek(): T;\n abstract get value(): T;\n\n subscribe(listener: () => void): Unsubscribe {\n this.runtime.assertActive();\n this.peek();\n\n const observer: ObserverNode = {\n dependencies: new Set(),\n onDependencyChanged: () => this.runtime.enqueueListener(listener),\n };\n\n this.dependents.add(observer);\n\n return () => this.dependents.delete(observer);\n }\n\n protected notify(): void {\n for (const dependent of [...this.dependents]) dependent.onDependencyChanged();\n }\n}\n\nclass SignalNode<T> extends ReactiveNode<T> implements Signal<T> {\n private current: T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, initial: T, options?: SignalOptions<T>) {\n super(runtime, options?.name);\n this.current = initial;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n this.runtime.track(this);\n\n return this.current;\n }\n\n set value(next: T) {\n this.runtime.assertActive();\n\n if (this.equals(this.current, next)) return;\n\n const previous = this.current;\n\n this.current = next;\n this.runtime.emit({ kind: 'write', name: this.name, next, previous });\n this.runtime.propagate(() => this.notify());\n }\n\n peek(): T {\n return this.current;\n }\n\n update(updater: (prev: T) => T): void {\n this.value = updater(this.current);\n }\n}\n\nclass ComputedNode<T> extends ReactiveNode<T> implements ObserverNode, Owned {\n readonly dependencies = new Set<Dependency>();\n private computing = false;\n private disposed = false;\n private dirty = true;\n private current: T | typeof UNSET = UNSET;\n private readonly derive: () => T;\n private readonly equals: (previous: T, next: T) => boolean;\n\n constructor(runtime: ReactiveRuntime, derive: () => T, options?: ComputedOptions<T>) {\n super(runtime, options?.name);\n this.derive = derive;\n this.equals = options?.equals ?? Object.is;\n }\n\n get value(): T {\n // Track before refresh: if refresh throws, the consumer still depends on\n // this computed and must be notified when a dependency change might let it\n // succeed. Without this, a first-run failure permanently severs the\n // consumer from the computed.\n this.runtime.track(this);\n this.refresh();\n\n return this.current as T;\n }\n\n peek(): T {\n this.refresh();\n\n return this.current as T;\n }\n\n onDependencyChanged(): void {\n if (this.disposed) return;\n\n if (!this.dirty) this.dirty = true;\n\n if (this.dependents.size > 0 && this.refresh()) this.notify();\n }\n\n dispose(): void {\n if (this.disposed) return;\n\n this.disposed = true;\n this.runtime.clearDependencies(this);\n this.dependents.clear();\n }\n\n private refresh(): boolean {\n if (!this.dirty || this.disposed) return false;\n\n if (this.computing) {\n const label = this.name === undefined ? '' : ` \"${this.name}\"`;\n\n throw new RippleComputedCycleError(`computed cycle detected${label}`);\n }\n\n this.computing = true;\n this.runtime.emit({ kind: 'compute', name: this.name });\n\n try {\n const next = this.runtime.collect(this, this.derive);\n const changed = this.current === UNSET || !this.equals(this.current as T, next);\n\n this.current = next;\n this.dirty = false;\n\n return changed;\n } finally {\n this.computing = false;\n }\n }\n}\n\nclass ScopeNode implements Scope {\n readonly disposalController = new AbortController();\n readonly owned = new Set<Owned>();\n readonly name: string | undefined;\n private isDisposed = false;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, name?: string) {\n this.runtime = runtime;\n this.name = name;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n run<T>(fn: () => T): T {\n if (this.isDisposed) throw new RippleDisposedScopeError('Cannot run a disposed scope.');\n\n return this.runtime.withScope(this, fn);\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n for (const owned of [...this.owned].reverse()) owned.dispose();\n this.owned.clear();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.name, node: 'scope' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n}\n\nclass EffectNode implements ObserverNode, EffectHandle {\n readonly dependencies = new Set<Dependency>();\n readonly disposalController = new AbortController();\n private cleanup: Cleanup | undefined;\n private isDisposed = false;\n private owner: ScopeNode | undefined;\n private scheduled = false;\n private readonly callback: () => Cleanup | undefined;\n private readonly options: EffectOptions | undefined;\n private readonly runtime: ReactiveRuntime;\n\n constructor(runtime: ReactiveRuntime, callback: () => Cleanup | undefined, options?: EffectOptions) {\n this.runtime = runtime;\n this.callback = callback;\n this.options = options;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n get disposalSignal(): AbortSignal {\n return this.disposalController.signal;\n }\n\n onDependencyChanged(): void {\n if (this.isDisposed) return;\n\n if (this.options?.scheduler === 'microtask') {\n if (this.scheduled) return;\n\n this.scheduled = true;\n queueMicrotask(() => {\n this.scheduled = false;\n\n if (!this.isDisposed) this.runtime.enqueue(this);\n });\n\n return;\n }\n\n this.runtime.enqueue(this);\n }\n\n run(): void {\n if (this.isDisposed) return;\n\n this.owner?.dispose();\n this.owner = undefined;\n this.runCleanup();\n this.runtime.emit({ kind: 'effect', name: this.options?.name });\n\n const owner = new ScopeNode(this.runtime);\n\n try {\n const cleanup = this.runtime.withEffectScope(owner, () => this.runtime.collectEffect(this, this.callback));\n\n this.owner = owner;\n this.cleanup = typeof cleanup === 'function' ? cleanup : undefined;\n } catch (error) {\n owner.dispose();\n this.runtime.report(error, { kind: 'effect', name: this.options?.name });\n }\n }\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.owner?.dispose();\n this.owner = undefined;\n this.runtime.clearDependencies(this);\n this.runCleanup();\n this.disposalController.abort();\n this.runtime.emit({ kind: 'dispose', name: this.options?.name, node: 'effect' });\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n private runCleanup(): void {\n const cleanup = this.cleanup;\n\n this.cleanup = undefined;\n\n if (cleanup === undefined) return;\n\n try {\n cleanup();\n } catch (error) {\n this.runtime.report(error, { kind: 'cleanup', name: this.options?.name });\n }\n }\n}\n\n/**\n * A runtime owns reactive graph state and lifetime. Separate instances isolate\n * applications and SSR requests without process-wide mutable hooks.\n */\nexport class ReactiveRuntime {\n private activeEffectScope: ScopeNode | undefined;\n private activeObserver: ObserverNode | undefined;\n private activeScope: ScopeNode;\n private isDisposed = false;\n private flushDepth = 0;\n private flushing = false;\n private readonly pending = new Set<EffectNode>();\n private readonly listeners = new Set<() => void>();\n private readonly rootScope: ScopeNode;\n private readonly observer: ReactiveObserver | undefined;\n private readonly onError: (error: unknown, context: ReactiveErrorContext) => void;\n\n constructor(options?: RippleOptions) {\n this.observer = options?.observer;\n this.onError =\n options?.onError ??\n ((error) => {\n queueMicrotask(() => {\n throw error;\n });\n });\n this.rootScope = new ScopeNode(this, 'runtime');\n this.activeScope = this.rootScope;\n }\n\n get disposed(): boolean {\n return this.isDisposed;\n }\n\n readonly signal = <T>(initial: T, options?: SignalOptions<T>): Signal<T> => {\n this.assertActive();\n\n return new SignalNode(this, initial, options);\n };\n\n readonly computed = <T>(derive: () => T, options?: ComputedOptions<T>): Readable<T> => {\n this.assertActive();\n\n const node = new ComputedNode(this, derive, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n\n return node;\n };\n\n readonly effect = (callback: () => Cleanup | undefined, options?: EffectOptions): EffectHandle => {\n this.assertActive();\n\n const node = new EffectNode(this, callback, options);\n\n (this.activeEffectScope ?? this.activeScope).owned.add(node);\n node.run();\n\n return node;\n };\n\n readonly createScope = (name?: string): Scope => {\n this.assertActive();\n\n const scope = new ScopeNode(this, name);\n\n // Scopes model explicit, caller-owned lifetimes. Unlike effects/computeds created during an\n // effect run, they deliberately attach to the enclosing scope rather than the per-run owner:\n // keyed DOM directives retain item scopes across reconciliation runs and dispose them only\n // when the item itself leaves the collection.\n this.activeScope.owned.add(scope);\n\n return scope;\n };\n\n readonly batch = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.propagate(fn);\n };\n\n readonly untrack = <T>(fn: () => T): T => {\n this.assertActive();\n\n return this.withObserver(undefined, fn);\n };\n\n dispose(): void {\n if (this.isDisposed) return;\n\n this.isDisposed = true;\n this.rootScope.dispose();\n }\n\n /** Internal node guard: disposed runtimes allow inert reads but reject graph work and mutation. */\n assertActive(): void {\n if (this.isDisposed) throw new RippleDisposedRuntimeError('Cannot use a disposed Ripple runtime.');\n }\n\n track(node: Dependency): void {\n const observer = this.activeObserver;\n\n if (observer?.collecting === undefined) return;\n\n observer.collecting.add(node);\n }\n\n clearDependencies(observer: ObserverNode): void {\n for (const dependency of observer.dependencies) dependency.dependents.delete(observer);\n observer.dependencies.clear();\n }\n\n collect<T>(observer: ObserverNode, fn: () => T): T {\n // On first run (no prior dependencies), commit partial dependencies even if\n // derive throws — otherwise the computed would have zero dependencies and never\n // be notified when its source changes, permanently stuck until a manual read.\n // On subsequent runs, keep previous dependencies (tested behavior).\n return this.collectWith(observer, fn, observer.dependencies.size === 0);\n }\n\n collectEffect<T>(observer: ObserverNode, fn: () => T): T {\n return this.collectWith(observer, fn, true);\n }\n\n withEffectScope<T>(scope: ScopeNode, fn: () => T): T {\n const previous = this.activeEffectScope;\n\n this.activeEffectScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previous;\n }\n }\n\n withObserver<T>(observer: ObserverNode | undefined, fn: () => T): T {\n const previous = this.activeObserver;\n\n this.activeObserver = observer;\n\n try {\n return fn();\n } finally {\n this.activeObserver = previous;\n }\n }\n\n withScope<T>(scope: ScopeNode, fn: () => T): T {\n const previousEffectScope = this.activeEffectScope;\n const previousScope = this.activeScope;\n\n this.activeEffectScope = undefined;\n this.activeScope = scope;\n\n try {\n return fn();\n } finally {\n this.activeEffectScope = previousEffectScope;\n this.activeScope = previousScope;\n }\n }\n\n enqueue(effect: EffectNode): void {\n this.pending.add(effect);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n enqueueListener(listener: () => void): void {\n this.listeners.add(listener);\n\n if (this.flushDepth === 0) this.flush();\n }\n\n propagate<T>(fn: () => T): T {\n this.flushDepth++;\n\n try {\n return fn();\n } finally {\n this.flushDepth--;\n\n if (this.flushDepth === 0) this.flush();\n }\n }\n\n emit(event: Parameters<ReactiveObserver>[0]): void {\n try {\n this.observer?.(event);\n } catch (error) {\n this.report(error, { kind: 'observer', name: event.name });\n }\n }\n\n report(error: unknown, context: ReactiveErrorContext): void {\n try {\n this.onError(error, context);\n } catch (reporterError) {\n queueMicrotask(() => {\n throw reporterError;\n });\n }\n }\n\n private collectWith<T>(observer: ObserverNode, fn: () => T, commitOnError: boolean): T {\n const previousObserver = this.activeObserver;\n const dependencies = new Set<Dependency>();\n\n observer.collecting = dependencies;\n this.activeObserver = observer;\n\n try {\n const result = fn();\n\n this.commitDependencies(observer, dependencies);\n\n return result;\n } catch (error) {\n if (commitOnError) this.commitDependencies(observer, dependencies);\n\n throw error;\n } finally {\n observer.collecting = undefined;\n this.activeObserver = previousObserver;\n }\n }\n\n private commitDependencies(observer: ObserverNode, next: Set<Dependency>): void {\n for (const dependency of observer.dependencies) {\n if (!next.has(dependency)) dependency.dependents.delete(observer);\n }\n\n for (const dependency of next) {\n if (!observer.dependencies.has(dependency)) dependency.dependents.add(observer);\n }\n\n observer.dependencies.clear();\n for (const dependency of next) observer.dependencies.add(dependency);\n }\n\n private flush(): void {\n if (this.flushing) return;\n\n this.flushing = true;\n\n let iterations = 0;\n\n try {\n while (this.pending.size > 0 || this.listeners.size > 0) {\n if (++iterations > MAX_FLUSH_ITERATIONS) {\n throw new RippleInfiniteLoopError(`infinite reactive flush (>${MAX_FLUSH_ITERATIONS} iterations)`);\n }\n\n const effects = [...this.pending];\n const listeners = [...this.listeners];\n\n this.pending.clear();\n this.listeners.clear();\n\n for (const effect of effects) effect.run();\n\n for (const listener of listeners) {\n try {\n listener();\n } catch (error) {\n this.report(error, { kind: 'listener' });\n }\n }\n }\n } finally {\n this.flushing = false;\n }\n }\n}\n\nexport const isReactive = <T>(value: T | Readable<T>): value is Readable<T> => {\n if (typeof value !== 'object' || value === null || !(REACTIVE in value)) return false;\n\n const candidate = value as { peek?: unknown; subscribe?: unknown };\n\n return typeof candidate.peek === 'function' && typeof candidate.subscribe === 'function';\n};\n"],"mappings":"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"}
|