5
5
* LICENSE file in the root directory of this source tree.
6
6
*/
7
7
8
+ import prettyFormat from "pretty-format" ;
8
9
import {
9
10
HIRFunction ,
10
11
IdentifierId ,
@@ -14,8 +15,15 @@ import {
14
15
} from "../HIR" ;
15
16
import { eachReactiveValueOperand } from "./visitors" ;
16
17
17
- /*
18
- * This pass supports the `fbt` translation system (https://facebook.github.io/fbt/).
18
+ /**
19
+ * This pass supports the
20
+ * This pass supports the `fbt` translation system (https://facebook.github.io/fbt/)
21
+ * as well as similar user-configurable macro-like APIs where it's important that
22
+ * the name of the function not be changed, and it's literal arguments not be turned
23
+ * into temporaries.
24
+ *
25
+ * ## FBT
26
+ *
19
27
* FBT provides the `<fbt>` JSX element and `fbt()` calls (which take params in the
20
28
* form of `<fbt:param>` children or `fbt.param()` arguments, respectively). These
21
29
* tags/functions have restrictions on what types of syntax may appear as props/children/
@@ -26,13 +34,22 @@ import { eachReactiveValueOperand } from "./visitors";
26
34
* operands to fbt tags/calls have the same scope as the tag/call itself.
27
35
*
28
36
* Note that this still allows the props/arguments of `<fbt:param>`/`fbt.param()`
29
- * to be independently memoized
37
+ * to be independently memoized.
38
+ *
39
+ * ## User-defined macro-like function
40
+ *
41
+ * Users can also specify their own functions to be treated similarly to fbt via the
42
+ * `customMacros` environment configuration.
30
43
*/
31
- export function memoizeFbtOperandsInSameScope ( fn : HIRFunction ) : void {
44
+ export function memoizeFbtAndMacroOperandsInSameScope ( fn : HIRFunction ) : void {
45
+ const fbtMacroTags = new Set ( [
46
+ ...FBT_TAGS ,
47
+ ...( fn . env . config . customMacros ?? [ ] ) ,
48
+ ] ) ;
32
49
const fbtValues : Set < IdentifierId > = new Set ( ) ;
33
50
while ( true ) {
34
51
let size = fbtValues . size ;
35
- visit ( fn , fbtValues ) ;
52
+ visit ( fn , fbtMacroTags , fbtValues ) ;
36
53
if ( size === fbtValues . size ) {
37
54
break ;
38
55
}
@@ -50,7 +67,11 @@ export const SINGLE_CHILD_FBT_TAGS: Set<string> = new Set([
50
67
"fbs:param" ,
51
68
] ) ;
52
69
53
- function visit ( fn : HIRFunction , fbtValues : Set < IdentifierId > ) : void {
70
+ function visit (
71
+ fn : HIRFunction ,
72
+ fbtMacroTags : Set < string > ,
73
+ fbtValues : Set < IdentifierId >
74
+ ) : void {
54
75
for ( const [ , block ] of fn . body . blocks ) {
55
76
for ( const instruction of block . instructions ) {
56
77
const { lvalue, value } = instruction ;
@@ -60,7 +81,7 @@ function visit(fn: HIRFunction, fbtValues: Set<IdentifierId>): void {
60
81
if (
61
82
value . kind === "Primitive" &&
62
83
typeof value . value === "string" &&
63
- FBT_TAGS . has ( value . value )
84
+ fbtMacroTags . has ( value . value )
64
85
) {
65
86
/*
66
87
* We don't distinguish between tag names and strings, so record
@@ -69,7 +90,7 @@ function visit(fn: HIRFunction, fbtValues: Set<IdentifierId>): void {
69
90
fbtValues . add ( lvalue . identifier . id ) ;
70
91
} else if (
71
92
value . kind === "LoadGlobal" &&
72
- FBT_TAGS . has ( value . binding . name )
93
+ fbtMacroTags . has ( value . binding . name )
73
94
) {
74
95
// Record references to `fbt` as a global
75
96
fbtValues . add ( lvalue . identifier . id ) ;
@@ -96,7 +117,7 @@ function visit(fn: HIRFunction, fbtValues: Set<IdentifierId>): void {
96
117
) ;
97
118
}
98
119
} else if (
99
- isFbtJsxExpression ( fbtValues , value ) ||
120
+ isFbtJsxExpression ( fbtMacroTags , fbtValues , value ) ||
100
121
isFbtJsxChild ( fbtValues , lvalue , value )
101
122
) {
102
123
const fbtScope = lvalue . identifier . scope ;
@@ -141,14 +162,15 @@ function isFbtCallExpression(
141
162
}
142
163
143
164
function isFbtJsxExpression (
165
+ fbtMacroTags : Set < string > ,
144
166
fbtValues : Set < IdentifierId > ,
145
167
value : ReactiveValue
146
168
) : boolean {
147
169
return (
148
170
value . kind === "JsxExpression" &&
149
171
( ( value . tag . kind === "Identifier" &&
150
172
fbtValues . has ( value . tag . identifier . id ) ) ||
151
- ( value . tag . kind === "BuiltinTag" && FBT_TAGS . has ( value . tag . name ) ) )
173
+ ( value . tag . kind === "BuiltinTag" && fbtMacroTags . has ( value . tag . name ) ) )
152
174
) ;
153
175
}
154
176
0 commit comments