77
88import  { NodePath ,  Scope }  from  '@babel/traverse' ; 
99import  *  as  t  from  '@babel/types' ; 
10- import  { Expression }  from  '@babel/types' ; 
1110import  invariant  from  'invariant' ; 
1211import  { 
1312  CompilerError , 
@@ -75,7 +74,7 @@ export function lower(
7574  parent : NodePath < t . Function >  |  null  =  null , 
7675) : Result < HIRFunction ,  CompilerError >  { 
7776  const  builder  =  new  HIRBuilder ( env ,  parent  ??  func ,  bindings ,  capturedRefs ) ; 
78-   const  context : Array < Place >  =  [ ] ; 
77+   const  context : HIRFunction [ 'context' ]  =  [ ] ; 
7978
8079  for  ( const  ref  of  capturedRefs  ??  [ ] )  { 
8180    context . push ( { 
@@ -3378,7 +3377,7 @@ function lowerFunction(
33783377  > , 
33793378) : LoweredFunction  |  null  { 
33803379  const  componentScope : Scope  =  builder . parentFunction . scope ; 
3381-   const  captured  =  gatherCapturedDeps ( builder ,   expr ,  componentScope ) ; 
3380+   const  capturedContext  =  gatherCapturedContext ( expr ,  componentScope ) ; 
33823381
33833382  /* 
33843383   * TODO(gsn): In the future, we could only pass in the context identifiers 
@@ -3392,7 +3391,7 @@ function lowerFunction(
33923391    expr , 
33933392    builder . environment , 
33943393    builder . bindings , 
3395-     [ ...builder . context ,  ...captured . identifiers ] , 
3394+     [ ...builder . context ,  ...capturedContext ] , 
33963395    builder . parentFunction , 
33973396  ) ; 
33983397  let  loweredFunc : HIRFunction ; 
@@ -3405,7 +3404,6 @@ function lowerFunction(
34053404  loweredFunc  =  lowering . unwrap ( ) ; 
34063405  return  { 
34073406    func : loweredFunc , 
3408-     dependencies : captured . refs , 
34093407  } ; 
34103408} 
34113409
@@ -4079,14 +4077,6 @@ function lowerAssignment(
40794077  } 
40804078} 
40814079
4082- function  isValidDependency ( path : NodePath < t . MemberExpression > ) : boolean  { 
4083-   const  parent : NodePath < t . Node >  =  path . parentPath ; 
4084-   return  ( 
4085-     ! path . node . computed  && 
4086-     ! ( parent . isCallExpression ( )  &&  parent . get ( 'callee' )  ===  path ) 
4087-   ) ; 
4088- } 
4089- 
40904080function  captureScopes ( { from,  to} : { from : Scope ;  to : Scope } ) : Set < Scope >  { 
40914081  let  scopes : Set < Scope >  =  new  Set ( ) ; 
40924082  while  ( from )  { 
@@ -4101,19 +4091,16 @@ function captureScopes({from, to}: {from: Scope; to: Scope}): Set<Scope> {
41014091  return  scopes ; 
41024092} 
41034093
4104- function  gatherCapturedDeps ( 
4105-   builder : HIRBuilder , 
4094+ function  gatherCapturedContext ( 
41064095  fn : NodePath < 
41074096    |  t . FunctionExpression 
41084097    |  t . ArrowFunctionExpression 
41094098    |  t . FunctionDeclaration 
41104099    |  t . ObjectMethod 
41114100  > , 
41124101  componentScope : Scope , 
4113- ) : { identifiers : Array < t . Identifier > ;  refs : Array < Place > }  { 
4114-   const  capturedIds : Map < t . Identifier ,  number >  =  new  Map ( ) ; 
4115-   const  capturedRefs : Set < Place >  =  new  Set ( ) ; 
4116-   const  seenPaths : Set < string >  =  new  Set ( ) ; 
4102+ ) : Array < t . Identifier >  { 
4103+   const  capturedIds  =  new  Set < t . Identifier > ( ) ; 
41174104
41184105  /* 
41194106   * Capture all the scopes from the parent of this function up to and including 
@@ -4124,33 +4111,11 @@ function gatherCapturedDeps(
41244111    to : componentScope , 
41254112  } ) ; 
41264113
4127-   function  addCapturedId ( bindingIdentifier : t . Identifier ) : number  { 
4128-     if  ( ! capturedIds . has ( bindingIdentifier ) )  { 
4129-       const  index  =  capturedIds . size ; 
4130-       capturedIds . set ( bindingIdentifier ,  index ) ; 
4131-       return  index ; 
4132-     }  else  { 
4133-       return  capturedIds . get ( bindingIdentifier ) ! ; 
4134-     } 
4135-   } 
4136- 
41374114  function  handleMaybeDependency ( 
4138-     path :
4139-       |  NodePath < t . MemberExpression > 
4140-       |  NodePath < t . Identifier > 
4141-       |  NodePath < t . JSXOpeningElement > , 
4115+     path : NodePath < t . Identifier >  |  NodePath < t . JSXOpeningElement > , 
41424116  ) : void { 
41434117    // Base context variable to depend on 
41444118    let  baseIdentifier : NodePath < t . Identifier >  |  NodePath < t . JSXIdentifier > ; 
4145-     /* 
4146-      * Base expression to depend on, which (for now) may contain non side-effectful 
4147-      * member expressions 
4148-      */ 
4149-     let  dependency :
4150-       |  NodePath < t . MemberExpression > 
4151-       |  NodePath < t . JSXMemberExpression > 
4152-       |  NodePath < t . Identifier > 
4153-       |  NodePath < t . JSXIdentifier > ; 
41544119    if  ( path . isJSXOpeningElement ( ) )  { 
41554120      const  name  =  path . get ( 'name' ) ; 
41564121      if  ( ! ( name . isJSXMemberExpression ( )  ||  name . isJSXIdentifier ( ) ) )  { 
@@ -4166,115 +4131,20 @@ function gatherCapturedDeps(
41664131        'Invalid logic in gatherCapturedDeps' , 
41674132      ) ; 
41684133      baseIdentifier  =  current ; 
4169- 
4170-       /* 
4171-        * Get the expression to depend on, which may involve PropertyLoads 
4172-        * for member expressions 
4173-        */ 
4174-       let  currentDep :
4175-         |  NodePath < t . JSXMemberExpression > 
4176-         |  NodePath < t . Identifier > 
4177-         |  NodePath < t . JSXIdentifier >  =  baseIdentifier ; 
4178- 
4179-       while  ( true )  { 
4180-         const  nextDep : null  |  NodePath < t . Node >  =  currentDep . parentPath ; 
4181-         if  ( nextDep  &&  nextDep . isJSXMemberExpression ( ) )  { 
4182-           currentDep  =  nextDep ; 
4183-         }  else  { 
4184-           break ; 
4185-         } 
4186-       } 
4187-       dependency  =  currentDep ; 
4188-     }  else  if  ( path . isMemberExpression ( ) )  { 
4189-       // Calculate baseIdentifier 
4190-       let  currentId : NodePath < Expression >  =  path ; 
4191-       while  ( currentId . isMemberExpression ( ) )  { 
4192-         currentId  =  currentId . get ( 'object' ) ; 
4193-       } 
4194-       if  ( ! currentId . isIdentifier ( ) )  { 
4195-         return ; 
4196-       } 
4197-       baseIdentifier  =  currentId ; 
4198- 
4199-       /* 
4200-        * Get the expression to depend on, which may involve PropertyLoads 
4201-        * for member expressions 
4202-        */ 
4203-       let  currentDep :
4204-         |  NodePath < t . MemberExpression > 
4205-         |  NodePath < t . Identifier > 
4206-         |  NodePath < t . JSXIdentifier >  =  baseIdentifier ; 
4207- 
4208-       while  ( true )  { 
4209-         const  nextDep : null  |  NodePath < t . Node >  =  currentDep . parentPath ; 
4210-         if  ( 
4211-           nextDep  && 
4212-           nextDep . isMemberExpression ( )  && 
4213-           isValidDependency ( nextDep ) 
4214-         )  { 
4215-           currentDep  =  nextDep ; 
4216-         }  else  { 
4217-           break ; 
4218-         } 
4219-       } 
4220- 
4221-       dependency  =  currentDep ; 
42224134    }  else  { 
42234135      baseIdentifier  =  path ; 
4224-       dependency  =  path ; 
42254136    } 
42264137
42274138    /* 
42284139     * Skip dependency path, as we already tried to recursively add it (+ all subexpressions) 
42294140     * as a dependency. 
42304141     */ 
4231-     dependency . skip ( ) ; 
4142+     path . skip ( ) ; 
42324143
42334144    // Add the base identifier binding as a dependency. 
42344145    const  binding  =  baseIdentifier . scope . getBinding ( baseIdentifier . node . name ) ; 
4235-     if  ( binding  ===  undefined  ||  ! pureScopes . has ( binding . scope ) )  { 
4236-       return ; 
4237-     } 
4238-     const  idKey  =  String ( addCapturedId ( binding . identifier ) ) ; 
4239- 
4240-     // Add the expression (potentially a memberexpr path) as a dependency. 
4241-     let  exprKey  =  idKey ; 
4242-     if  ( dependency . isMemberExpression ( ) )  { 
4243-       let  pathTokens  =  [ ] ; 
4244-       let  current : NodePath < Expression >  =  dependency ; 
4245-       while  ( current . isMemberExpression ( ) )  { 
4246-         const  property  =  current . get ( 'property' )  as  NodePath < t . Identifier > ; 
4247-         pathTokens . push ( property . node . name ) ; 
4248-         current  =  current . get ( 'object' ) ; 
4249-       } 
4250- 
4251-       exprKey  +=  '.'  +  pathTokens . reverse ( ) . join ( '.' ) ; 
4252-     }  else  if  ( dependency . isJSXMemberExpression ( ) )  { 
4253-       let  pathTokens  =  [ ] ; 
4254-       let  current : NodePath < t . JSXMemberExpression  |  t . JSXIdentifier >  = 
4255-         dependency ; 
4256-       while  ( current . isJSXMemberExpression ( ) )  { 
4257-         const  property  =  current . get ( 'property' ) ; 
4258-         pathTokens . push ( property . node . name ) ; 
4259-         current  =  current . get ( 'object' ) ; 
4260-       } 
4261-     } 
4262- 
4263-     if  ( ! seenPaths . has ( exprKey ) )  { 
4264-       let  loweredDep : Place ; 
4265-       if  ( dependency . isJSXIdentifier ( ) )  { 
4266-         loweredDep  =  lowerValueToTemporary ( builder ,  { 
4267-           kind : 'LoadLocal' , 
4268-           place : lowerIdentifier ( builder ,  dependency ) , 
4269-           loc : path . node . loc  ??  GeneratedSource , 
4270-         } ) ; 
4271-       }  else  if  ( dependency . isJSXMemberExpression ( ) )  { 
4272-         loweredDep  =  lowerJsxMemberExpression ( builder ,  dependency ) ; 
4273-       }  else  { 
4274-         loweredDep  =  lowerExpressionToTemporary ( builder ,  dependency ) ; 
4275-       } 
4276-       capturedRefs . add ( loweredDep ) ; 
4277-       seenPaths . add ( exprKey ) ; 
4146+     if  ( binding  !==  undefined  &&  pureScopes . has ( binding . scope ) )  { 
4147+       capturedIds . add ( binding . identifier ) ; 
42784148    } 
42794149  } 
42804150
@@ -4305,13 +4175,13 @@ function gatherCapturedDeps(
43054175        return ; 
43064176      }  else  if  ( path . isJSXElement ( ) )  { 
43074177        handleMaybeDependency ( path . get ( 'openingElement' ) ) ; 
4308-       }  else  if  ( path . isMemberExpression ( )   ||   path . isIdentifier ( ) )  { 
4178+       }  else  if  ( path . isIdentifier ( ) )  { 
43094179        handleMaybeDependency ( path ) ; 
43104180      } 
43114181    } , 
43124182  } ) ; 
43134183
4314-   return  { identifiers :  [ ...capturedIds . keys ( ) ] ,   refs :  [ ... capturedRefs ] } ; 
4184+   return  [ ...capturedIds . keys ( ) ] ; 
43154185} 
43164186
43174187function  notNull < T > ( value : T  |  null ) : value  is T  { 
0 commit comments