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 ( {
@@ -3377,7 +3376,7 @@ function lowerFunction(
33773376 > ,
33783377) : LoweredFunction | null {
33793378 const componentScope : Scope = builder . parentFunction . scope ;
3380- const captured = gatherCapturedDeps ( builder , expr , componentScope ) ;
3379+ const capturedContext = gatherCapturedContext ( expr , componentScope ) ;
33813380
33823381 /*
33833382 * TODO(gsn): In the future, we could only pass in the context identifiers
@@ -3391,7 +3390,7 @@ function lowerFunction(
33913390 expr ,
33923391 builder . environment ,
33933392 builder . bindings ,
3394- [ ...builder . context , ...captured . identifiers ] ,
3393+ [ ...builder . context , ...capturedContext ] ,
33953394 builder . parentFunction ,
33963395 ) ;
33973396 let loweredFunc : HIRFunction ;
@@ -3404,7 +3403,6 @@ function lowerFunction(
34043403 loweredFunc = lowering . unwrap ( ) ;
34053404 return {
34063405 func : loweredFunc ,
3407- dependencies : captured . refs ,
34083406 } ;
34093407}
34103408
@@ -4078,14 +4076,6 @@ function lowerAssignment(
40784076 }
40794077}
40804078
4081- function isValidDependency ( path : NodePath < t . MemberExpression > ) : boolean {
4082- const parent : NodePath < t . Node > = path . parentPath ;
4083- return (
4084- ! path . node . computed &&
4085- ! ( parent . isCallExpression ( ) && parent . get ( 'callee' ) === path )
4086- ) ;
4087- }
4088-
40894079function captureScopes ( { from, to} : { from : Scope ; to : Scope } ) : Set < Scope > {
40904080 let scopes : Set < Scope > = new Set ( ) ;
40914081 while ( from ) {
@@ -4100,19 +4090,16 @@ function captureScopes({from, to}: {from: Scope; to: Scope}): Set<Scope> {
41004090 return scopes ;
41014091}
41024092
4103- function gatherCapturedDeps (
4104- builder : HIRBuilder ,
4093+ function gatherCapturedContext (
41054094 fn : NodePath <
41064095 | t . FunctionExpression
41074096 | t . ArrowFunctionExpression
41084097 | t . FunctionDeclaration
41094098 | t . ObjectMethod
41104099 > ,
41114100 componentScope : Scope ,
4112- ) : { identifiers : Array < t . Identifier > ; refs : Array < Place > } {
4113- const capturedIds : Map < t . Identifier , number > = new Map ( ) ;
4114- const capturedRefs : Set < Place > = new Set ( ) ;
4115- const seenPaths : Set < string > = new Set ( ) ;
4101+ ) : Array < t . Identifier > {
4102+ const capturedIds = new Set < t . Identifier > ( ) ;
41164103
41174104 /*
41184105 * Capture all the scopes from the parent of this function up to and including
@@ -4123,33 +4110,11 @@ function gatherCapturedDeps(
41234110 to : componentScope ,
41244111 } ) ;
41254112
4126- function addCapturedId ( bindingIdentifier : t . Identifier ) : number {
4127- if ( ! capturedIds . has ( bindingIdentifier ) ) {
4128- const index = capturedIds . size ;
4129- capturedIds . set ( bindingIdentifier , index ) ;
4130- return index ;
4131- } else {
4132- return capturedIds . get ( bindingIdentifier ) ! ;
4133- }
4134- }
4135-
41364113 function handleMaybeDependency (
4137- path :
4138- | NodePath < t . MemberExpression >
4139- | NodePath < t . Identifier >
4140- | NodePath < t . JSXOpeningElement > ,
4114+ path : NodePath < t . Identifier > | NodePath < t . JSXOpeningElement > ,
41414115 ) : void {
41424116 // Base context variable to depend on
41434117 let baseIdentifier : NodePath < t . Identifier > | NodePath < t . JSXIdentifier > ;
4144- /*
4145- * Base expression to depend on, which (for now) may contain non side-effectful
4146- * member expressions
4147- */
4148- let dependency :
4149- | NodePath < t . MemberExpression >
4150- | NodePath < t . JSXMemberExpression >
4151- | NodePath < t . Identifier >
4152- | NodePath < t . JSXIdentifier > ;
41534118 if ( path . isJSXOpeningElement ( ) ) {
41544119 const name = path . get ( 'name' ) ;
41554120 if ( ! ( name . isJSXMemberExpression ( ) || name . isJSXIdentifier ( ) ) ) {
@@ -4165,115 +4130,20 @@ function gatherCapturedDeps(
41654130 'Invalid logic in gatherCapturedDeps' ,
41664131 ) ;
41674132 baseIdentifier = current ;
4168-
4169- /*
4170- * Get the expression to depend on, which may involve PropertyLoads
4171- * for member expressions
4172- */
4173- let currentDep :
4174- | NodePath < t . JSXMemberExpression >
4175- | NodePath < t . Identifier >
4176- | NodePath < t . JSXIdentifier > = baseIdentifier ;
4177-
4178- while ( true ) {
4179- const nextDep : null | NodePath < t . Node > = currentDep . parentPath ;
4180- if ( nextDep && nextDep . isJSXMemberExpression ( ) ) {
4181- currentDep = nextDep ;
4182- } else {
4183- break ;
4184- }
4185- }
4186- dependency = currentDep ;
4187- } else if ( path . isMemberExpression ( ) ) {
4188- // Calculate baseIdentifier
4189- let currentId : NodePath < Expression > = path ;
4190- while ( currentId . isMemberExpression ( ) ) {
4191- currentId = currentId . get ( 'object' ) ;
4192- }
4193- if ( ! currentId . isIdentifier ( ) ) {
4194- return ;
4195- }
4196- baseIdentifier = currentId ;
4197-
4198- /*
4199- * Get the expression to depend on, which may involve PropertyLoads
4200- * for member expressions
4201- */
4202- let currentDep :
4203- | NodePath < t . MemberExpression >
4204- | NodePath < t . Identifier >
4205- | NodePath < t . JSXIdentifier > = baseIdentifier ;
4206-
4207- while ( true ) {
4208- const nextDep : null | NodePath < t . Node > = currentDep . parentPath ;
4209- if (
4210- nextDep &&
4211- nextDep . isMemberExpression ( ) &&
4212- isValidDependency ( nextDep )
4213- ) {
4214- currentDep = nextDep ;
4215- } else {
4216- break ;
4217- }
4218- }
4219-
4220- dependency = currentDep ;
42214133 } else {
42224134 baseIdentifier = path ;
4223- dependency = path ;
42244135 }
42254136
42264137 /*
42274138 * Skip dependency path, as we already tried to recursively add it (+ all subexpressions)
42284139 * as a dependency.
42294140 */
4230- dependency . skip ( ) ;
4141+ path . skip ( ) ;
42314142
42324143 // Add the base identifier binding as a dependency.
42334144 const binding = baseIdentifier . scope . getBinding ( baseIdentifier . node . name ) ;
4234- if ( binding === undefined || ! pureScopes . has ( binding . scope ) ) {
4235- return ;
4236- }
4237- const idKey = String ( addCapturedId ( binding . identifier ) ) ;
4238-
4239- // Add the expression (potentially a memberexpr path) as a dependency.
4240- let exprKey = idKey ;
4241- if ( dependency . isMemberExpression ( ) ) {
4242- let pathTokens = [ ] ;
4243- let current : NodePath < Expression > = dependency ;
4244- while ( current . isMemberExpression ( ) ) {
4245- const property = current . get ( 'property' ) as NodePath < t . Identifier > ;
4246- pathTokens . push ( property . node . name ) ;
4247- current = current . get ( 'object' ) ;
4248- }
4249-
4250- exprKey += '.' + pathTokens . reverse ( ) . join ( '.' ) ;
4251- } else if ( dependency . isJSXMemberExpression ( ) ) {
4252- let pathTokens = [ ] ;
4253- let current : NodePath < t . JSXMemberExpression | t . JSXIdentifier > =
4254- dependency ;
4255- while ( current . isJSXMemberExpression ( ) ) {
4256- const property = current . get ( 'property' ) ;
4257- pathTokens . push ( property . node . name ) ;
4258- current = current . get ( 'object' ) ;
4259- }
4260- }
4261-
4262- if ( ! seenPaths . has ( exprKey ) ) {
4263- let loweredDep : Place ;
4264- if ( dependency . isJSXIdentifier ( ) ) {
4265- loweredDep = lowerValueToTemporary ( builder , {
4266- kind : 'LoadLocal' ,
4267- place : lowerIdentifier ( builder , dependency ) ,
4268- loc : path . node . loc ?? GeneratedSource ,
4269- } ) ;
4270- } else if ( dependency . isJSXMemberExpression ( ) ) {
4271- loweredDep = lowerJsxMemberExpression ( builder , dependency ) ;
4272- } else {
4273- loweredDep = lowerExpressionToTemporary ( builder , dependency ) ;
4274- }
4275- capturedRefs . add ( loweredDep ) ;
4276- seenPaths . add ( exprKey ) ;
4145+ if ( binding !== undefined && pureScopes . has ( binding . scope ) ) {
4146+ capturedIds . add ( binding . identifier ) ;
42774147 }
42784148 }
42794149
@@ -4304,13 +4174,13 @@ function gatherCapturedDeps(
43044174 return ;
43054175 } else if ( path . isJSXElement ( ) ) {
43064176 handleMaybeDependency ( path . get ( 'openingElement' ) ) ;
4307- } else if ( path . isMemberExpression ( ) || path . isIdentifier ( ) ) {
4177+ } else if ( path . isIdentifier ( ) ) {
43084178 handleMaybeDependency ( path ) ;
43094179 }
43104180 } ,
43114181 } ) ;
43124182
4313- return { identifiers : [ ...capturedIds . keys ( ) ] , refs : [ ... capturedRefs ] } ;
4183+ return [ ...capturedIds . keys ( ) ] ;
43144184}
43154185
43164186function notNull < T > ( value : T | null ) : value is T {
0 commit comments