1+ import { OwlError } from "../common/owl_error" ;
2+ import { Atom , Computation , ComputationState } from "../common/types" ;
13import type { App , Env } from "./app" ;
24import { BDom , VNode } from "./blockdom" ;
35import { Component , ComponentConstructor , Props } from "./component" ;
46import { fibersInError } from "./error_handling" ;
5- import { OwlError } from "../common/owl_error" ;
67import { Fiber , makeChildFiber , makeRootFiber , MountFiber , MountOptions } from "./fibers" ;
7- import { clearReactivesForCallback , getSubscriptions , reactive , targets } from "./reactivity" ;
8+ import { reactive } from "./reactivity" ;
9+ import { getCurrentComputation , setComputation , withoutReactivity } from "./signals" ;
810import { STATUS } from "./status" ;
9- import { batched , Callback } from "./utils" ;
1011
1112let currentNode : ComponentNode | null = null ;
1213
@@ -42,7 +43,6 @@ function applyDefaultProps<P extends object>(props: P, defaultProps: Partial<P>)
4243// Integration with reactivity system (useState)
4344// -----------------------------------------------------------------------------
4445
45- const batchedRenderFunctions = new WeakMap < ComponentNode , Callback > ( ) ;
4646/**
4747 * Creates a reactive object that will be observed by the current component.
4848 * Reading data from the returned object (eg during rendering) will cause the
@@ -54,15 +54,7 @@ const batchedRenderFunctions = new WeakMap<ComponentNode, Callback>();
5454 * @see reactive
5555 */
5656export function useState < T extends object > ( state : T ) : T {
57- const node = getCurrent ( ) ;
58- let render = batchedRenderFunctions . get ( node ) ! ;
59- if ( ! render ) {
60- render = batched ( node . render . bind ( node , false ) ) ;
61- batchedRenderFunctions . set ( node , render ) ;
62- // manual implementation of onWillDestroy to break cyclic dependency
63- node . willDestroy . push ( clearReactivesForCallback . bind ( null , render ) ) ;
64- }
65- return reactive ( state , render ) ;
57+ return reactive ( state ) ;
6658}
6759
6860// -----------------------------------------------------------------------------
@@ -96,6 +88,7 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
9688 willPatch : LifecycleHook [ ] = [ ] ;
9789 patched : LifecycleHook [ ] = [ ] ;
9890 willDestroy : LifecycleHook [ ] = [ ] ;
91+ signalComputation : Computation ;
9992
10093 constructor (
10194 C : ComponentConstructor < P , E > ,
@@ -109,23 +102,26 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
109102 this . parent = parent ;
110103 this . props = props ;
111104 this . parentKey = parentKey ;
105+ this . signalComputation = {
106+ value : undefined ,
107+ compute : ( ) => this . render ( false ) ,
108+ sources : new Set < Atom > ( ) ,
109+ state : ComputationState . EXECUTED ,
110+ } ;
112111 const defaultProps = C . defaultProps ;
113112 props = Object . assign ( { } , props ) ;
114113 if ( defaultProps ) {
115114 applyDefaultProps ( props , defaultProps ) ;
116115 }
117116 const env = ( parent && parent . childEnv ) || app . env ;
118117 this . childEnv = env ;
119- for ( const key in props ) {
120- const prop = props [ key ] ;
121- if ( prop && typeof prop === "object" && targets . has ( prop ) ) {
122- props [ key ] = useState ( prop ) ;
123- }
124- }
118+ const previousComputation = getCurrentComputation ( ) ;
119+ setComputation ( this . signalComputation ) ;
125120 this . component = new C ( props , env , this ) ;
126121 const ctx = Object . assign ( Object . create ( this . component ) , { this : this . component } ) ;
127122 this . renderFn = app . getTemplate ( C . template ) . bind ( this . component , ctx , this ) ;
128123 this . component . setup ( ) ;
124+ setComputation ( previousComputation ) ;
129125 currentNode = null ;
130126 }
131127
@@ -142,7 +138,11 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
142138 }
143139 const component = this . component ;
144140 try {
145- await Promise . all ( this . willStart . map ( ( f ) => f . call ( component ) ) ) ;
141+ let prom : Promise < any [ ] > ;
142+ withoutReactivity ( ( ) => {
143+ prom = Promise . all ( this . willStart . map ( ( f ) => f . call ( component ) ) ) ;
144+ } ) ;
145+ await prom ! ;
146146 } catch ( e ) {
147147 this . app . handleError ( { node : this , error : e } ) ;
148148 return ;
@@ -257,16 +257,11 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
257257 applyDefaultProps ( props , defaultProps ) ;
258258 }
259259
260- currentNode = this ;
261- for ( const key in props ) {
262- const prop = props [ key ] ;
263- if ( prop && typeof prop === "object" && targets . has ( prop ) ) {
264- props [ key ] = useState ( prop ) ;
265- }
266- }
267- currentNode = null ;
268- const prom = Promise . all ( this . willUpdateProps . map ( ( f ) => f . call ( component , props ) ) ) ;
269- await prom ;
260+ let prom : Promise < any [ ] > ;
261+ withoutReactivity ( ( ) => {
262+ prom = Promise . all ( this . willUpdateProps . map ( ( f ) => f . call ( component , props ) ) ) ;
263+ } ) ;
264+ await prom ! ;
270265 if ( fiber !== this . fiber ) {
271266 return ;
272267 }
@@ -383,9 +378,4 @@ export class ComponentNode<P extends Props = any, E = any> implements VNode<Comp
383378 get name ( ) : string {
384379 return this . component . constructor . name ;
385380 }
386-
387- get subscriptions ( ) : ReturnType < typeof getSubscriptions > {
388- const render = batchedRenderFunctions . get ( this ) ;
389- return render ? getSubscriptions ( render ) : [ ] ;
390- }
391381}
0 commit comments