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