mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
[compiler][ez] Option to bail out on blocklisted imports
ghstack-source-id: 540d154b25e49a83683a05fc9326dbd0ad59a6bd Pull Request resolved: https://github.com/facebook/react/pull/30643
This commit is contained in:
@@ -8,9 +8,33 @@
|
||||
import {NodePath} from '@babel/core';
|
||||
import * as t from '@babel/types';
|
||||
import {CompilerError} from '../CompilerError';
|
||||
import {ExternalFunction, GeneratedSource} from '../HIR';
|
||||
import {EnvironmentConfig, ExternalFunction, GeneratedSource} from '../HIR';
|
||||
import {getOrInsertDefault} from '../Utils/utils';
|
||||
|
||||
export function validateRestrictedImports(
|
||||
path: NodePath<t.Program>,
|
||||
{validateBlocklistedImports}: EnvironmentConfig,
|
||||
): void {
|
||||
if (
|
||||
validateBlocklistedImports == null ||
|
||||
validateBlocklistedImports.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
const restrictedImports = new Set(validateBlocklistedImports);
|
||||
path.traverse({
|
||||
ImportDeclaration(importDeclPath) {
|
||||
if (restrictedImports.has(importDeclPath.node.source.value)) {
|
||||
CompilerError.throwTodo({
|
||||
reason: 'Bailing out due to blocklisted import',
|
||||
description: `Import from module ${importDeclPath.node.source.value}`,
|
||||
loc: importDeclPath.node.loc ?? null,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function addImportsToProgram(
|
||||
path: NodePath<t.Program>,
|
||||
importList: Array<ExternalFunction>,
|
||||
|
||||
@@ -24,7 +24,11 @@ import {isComponentDeclaration} from '../Utils/ComponentDeclaration';
|
||||
import {isHookDeclaration} from '../Utils/HookDeclaration';
|
||||
import {assertExhaustive} from '../Utils/utils';
|
||||
import {insertGatedFunctionDeclaration} from './Gating';
|
||||
import {addImportsToProgram, updateMemoCacheFunctionImport} from './Imports';
|
||||
import {
|
||||
addImportsToProgram,
|
||||
updateMemoCacheFunctionImport,
|
||||
validateRestrictedImports,
|
||||
} from './Imports';
|
||||
import {PluginOptions} from './Options';
|
||||
import {compileFn} from './Pipeline';
|
||||
import {
|
||||
@@ -296,6 +300,7 @@ export function compileProgram(
|
||||
});
|
||||
}
|
||||
const environment = environmentResult.unwrap();
|
||||
validateRestrictedImports(program, environment);
|
||||
const useMemoCacheIdentifier = program.scope.generateUidIdentifier('c');
|
||||
const moduleName = pass.opts.runtimeModule ?? 'react/compiler-runtime';
|
||||
|
||||
|
||||
@@ -238,6 +238,7 @@ const EnvironmentConfigSchema = z.object({
|
||||
* this option to the empty array.
|
||||
*/
|
||||
validateNoCapitalizedCalls: z.nullable(z.array(z.string())).default(null),
|
||||
validateBlocklistedImports: z.nullable(z.array(z.string())).default(null),
|
||||
|
||||
/*
|
||||
* When enabled, the compiler assumes that hooks follow the Rules of React:
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @validateBlocklistedImports(DangerousImport)
|
||||
import {foo} from 'DangerousImport';
|
||||
import {useIdentity} from 'shared-runtime';
|
||||
|
||||
function useHook() {
|
||||
useIdentity(foo);
|
||||
return;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
1 | // @validateBlocklistedImports(DangerousImport)
|
||||
> 2 | import {foo} from 'DangerousImport';
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Todo: Bailing out due to blocklisted import. Import from module DangerousImport (2:2)
|
||||
3 | import {useIdentity} from 'shared-runtime';
|
||||
4 |
|
||||
5 | function useHook() {
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// @validateBlocklistedImports(DangerousImport)
|
||||
import {foo} from 'DangerousImport';
|
||||
import {useIdentity} from 'shared-runtime';
|
||||
|
||||
function useHook() {
|
||||
useIdentity(foo);
|
||||
return;
|
||||
}
|
||||
@@ -47,6 +47,7 @@ function makePluginOptions(
|
||||
let validatePreserveExistingMemoizationGuarantees = false;
|
||||
let enableChangeDetectionForDebugging = null;
|
||||
let customMacros = null;
|
||||
let validateBlocklistedImports = null;
|
||||
|
||||
if (firstLine.indexOf('@compilationMode(annotation)') !== -1) {
|
||||
assert(
|
||||
@@ -155,6 +156,19 @@ function makePluginOptions(
|
||||
.filter(s => s.length > 0);
|
||||
}
|
||||
|
||||
const validateBlocklistedImportsMatch =
|
||||
/@validateBlocklistedImports\(([^)]+)\)/.exec(firstLine);
|
||||
if (
|
||||
validateBlocklistedImportsMatch &&
|
||||
validateBlocklistedImportsMatch.length > 1 &&
|
||||
validateBlocklistedImportsMatch[1].trim().length > 0
|
||||
) {
|
||||
validateBlocklistedImports = validateBlocklistedImportsMatch[1]
|
||||
.split(' ')
|
||||
.map(s => s.trim())
|
||||
.filter(s => s.length > 0);
|
||||
}
|
||||
|
||||
let lowerContextAccess = null;
|
||||
if (firstLine.includes('@lowerContextAccess')) {
|
||||
lowerContextAccess = {
|
||||
@@ -216,6 +230,7 @@ function makePluginOptions(
|
||||
validatePreserveExistingMemoizationGuarantees,
|
||||
enableChangeDetectionForDebugging,
|
||||
lowerContextAccess,
|
||||
validateBlocklistedImports,
|
||||
},
|
||||
compilationMode,
|
||||
logger,
|
||||
|
||||
Reference in New Issue
Block a user