61
}
62
63
/*
64
- * Matches `import { ... } from 'react';`
65
- * but not `import * as React from 'react';`
64
+ * Matches `import { ... } from <moduleName>;`
65
+ * but not `import * as React from <moduleName>;`
66
*/
67
-export function isNonNamespacedImportOfReact(
68
- importDeclPath: NodePath<t.ImportDeclaration>
67
+function isNonNamespacedImport(
68
+ importDeclPath: NodePath<t.ImportDeclaration>,
69
+ moduleName: string
70
): boolean {
71
return (
71
- importDeclPath.get("source").node.value === "react" &&
72
+ importDeclPath.get("source").node.value === moduleName &&
73
importDeclPath
74
.get("specifiers")
75
.every((specifier) => specifier.isImportSpecifier()) &&
78
);
79
}
80
80
-export function findExistingImports(program: NodePath<t.Program>): {
81
+function findExistingImports(
82
+ program: NodePath<t.Program>,
83
+ moduleName: string
84
+): {
85
didInsertUseMemoCache: boolean;
82
- hasExistingReactImport: boolean;
86
+ hasExistingImport: boolean;
87
} {
88
let didInsertUseMemoCache = false;
85
- let hasExistingReactImport = false;
89
+ let hasExistingImport = false;
90
program.traverse({
91
CallExpression(callExprPath) {
92
const callee = callExprPath.get("callee");
101
}
102
},
103
ImportDeclaration(importDeclPath) {
100
- if (isNonNamespacedImportOfReact(importDeclPath)) {
101
- hasExistingReactImport = true;
104
+ if (isNonNamespacedImport(importDeclPath, moduleName)) {
105
+ hasExistingImport = true;
106
}
107
},
108
});
109
110
return {
111
didInsertUseMemoCache,
108
- hasExistingReactImport,
112
+ hasExistingImport,
113
};
114
}
115
116
/*
113
- * If an existing import of React exists (ie `import {useMemo} from 'React'`), inject useMemoCache
117
+ * If an existing import of React exists (ie `import {useMemo} from 'react'`), inject useMemoCache
118
* into the list of destructured variables.
119
*/
116
-export function updateExistingReactImportDeclaration(
117
- program: NodePath<t.Program>
120
+function updateExistingImportDeclaration(
121
+ program: NodePath<t.Program>,
122
+ moduleName: string
123
): boolean {
124
let didInsertUseMemoCache = false;
125
program.traverse({
126
ImportDeclaration(importDeclPath) {
127
if (
128
!didInsertUseMemoCache &&
124
- isNonNamespacedImportOfReact(importDeclPath)
129
+ isNonNamespacedImport(importDeclPath, moduleName)
130
) {
131
importDeclPath.pushContainer(
132
"specifiers",
128
- t.importSpecifier(
129
- t.identifier("useMemoCache"),
130
- t.identifier("unstable_useMemoCache")
131
- )
133
+ t.importSpecifier(t.identifier("useMemoCache"), t.identifier("c"))
134
);
135
didInsertUseMemoCache = true;
136
}
143
program: NodePath<t.Program>,
144
options: PluginOptions
145
): void {
146
+ const moduleName = options.runtimeModule ?? "react/compiler-runtime";
147
/*
148
* If there isn't already an import of * as React, insert it so useMemoCache doesn't
149
* throw
150
*/
148
- const { didInsertUseMemoCache, hasExistingReactImport } =
149
- findExistingImports(program);
151
+ const { didInsertUseMemoCache, hasExistingImport } = findExistingImports(
152
+ program,
153
+ moduleName
154
+ );
155
151
- // unstable_useMemoCache wasn't already imported, nothing to do
156
if (!didInsertUseMemoCache) {
157
+ // useMemoCache was not generated, nothing to do
158
return;
159
}
160
156
- if (options.enableUseMemoCachePolyfill === false) {
157
- /*
158
- * If Forget did successfully compile inject/update an import of
159
- * `import {unstable_useMemoCache as useMemoCache} from 'react'` and rename
160
- * `React.unstable_useMemoCache(n)` to `useMemoCache(n)`;
161
- */
162
- if (hasExistingReactImport) {
163
- const didUpdateImport = updateExistingReactImportDeclaration(program);
164
- if (didUpdateImport === false) {
165
- throw new Error(
166
- "Expected an ImportDeclaration of react in order to update ImportSpecifiers with useMemoCache"
167
- );
168
- }
169
- } else {
170
- addUseMemoCacheImportDeclaration(program, "react");
161
+ if (hasExistingImport) {
162
+ const didUpdateImport = updateExistingImportDeclaration(
163
+ program,
164
+ moduleName
165
+ );
166
+ if (!didUpdateImport) {
167
+ throw new Error(
168
+ `Expected an ImportDeclaration of \`${moduleName}\` in order to update ImportSpecifiers with useMemoCache`
169
+ );
170
}
171
} else {
173
- // import useMemoCache from userspace module
174
- addUseMemoCacheImportDeclaration(program, "react-forget-runtime");
172
+ addUseMemoCacheImportDeclaration(program, moduleName);
173
}
174
}
175
180
program.unshiftContainer(
181
"body",
182
t.importDeclaration(
185
- [
186
- t.importSpecifier(
187
- t.identifier("useMemoCache"),
188
- t.identifier("unstable_useMemoCache")
189
- ),
190
- ],
183
+ [t.importSpecifier(t.identifier("useMemoCache"), t.identifier("c"))],
184
t.stringLiteral(moduleName)
185
)
186
);