Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51620ac79c |
@@ -41,6 +41,10 @@ const DynamicGatingOptionsSchema = z.object({
|
|||||||
source: z.string(),
|
source: z.string(),
|
||||||
});
|
});
|
||||||
export type DynamicGatingOptions = z.infer<typeof DynamicGatingOptionsSchema>;
|
export type DynamicGatingOptions = z.infer<typeof DynamicGatingOptionsSchema>;
|
||||||
|
const CustomOptOutDirectiveSchema = z
|
||||||
|
.nullable(z.array(z.string()))
|
||||||
|
.default(null);
|
||||||
|
type CustomOptOutDirective = z.infer<typeof CustomOptOutDirectiveSchema>;
|
||||||
|
|
||||||
export type PluginOptions = {
|
export type PluginOptions = {
|
||||||
environment: EnvironmentConfig;
|
environment: EnvironmentConfig;
|
||||||
@@ -132,6 +136,11 @@ export type PluginOptions = {
|
|||||||
*/
|
*/
|
||||||
ignoreUseNoForget: boolean;
|
ignoreUseNoForget: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unstable / do not use
|
||||||
|
*/
|
||||||
|
customOptOutDirectives: CustomOptOutDirective;
|
||||||
|
|
||||||
sources: Array<string> | ((filename: string) => boolean) | null;
|
sources: Array<string> | ((filename: string) => boolean) | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -278,6 +287,7 @@ export const defaultOptions: PluginOptions = {
|
|||||||
return filename.indexOf('node_modules') === -1;
|
return filename.indexOf('node_modules') === -1;
|
||||||
},
|
},
|
||||||
enableReanimatedCheck: true,
|
enableReanimatedCheck: true,
|
||||||
|
customOptOutDirectives: null,
|
||||||
target: '19',
|
target: '19',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
@@ -338,6 +348,21 @@ export function parsePluginOptions(obj: unknown): PluginOptions {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'customOptOutDirectives': {
|
||||||
|
const result = CustomOptOutDirectiveSchema.safeParse(value);
|
||||||
|
if (result.success) {
|
||||||
|
parsedOptions[key] = result.data;
|
||||||
|
} else {
|
||||||
|
CompilerError.throwInvalidConfig({
|
||||||
|
reason:
|
||||||
|
'Could not parse custom opt out directives. Update React Compiler config to fix the error',
|
||||||
|
description: `${fromZodError(result.error)}`,
|
||||||
|
loc: null,
|
||||||
|
suggestions: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
parsedOptions[key] = value;
|
parsedOptions[key] = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,16 @@ export function tryFindDirectiveEnablingMemoization(
|
|||||||
|
|
||||||
export function findDirectiveDisablingMemoization(
|
export function findDirectiveDisablingMemoization(
|
||||||
directives: Array<t.Directive>,
|
directives: Array<t.Directive>,
|
||||||
|
{customOptOutDirectives}: PluginOptions,
|
||||||
): t.Directive | null {
|
): t.Directive | null {
|
||||||
|
if (customOptOutDirectives != null) {
|
||||||
|
return (
|
||||||
|
directives.find(
|
||||||
|
directive =>
|
||||||
|
customOptOutDirectives.indexOf(directive.value.value) !== -1,
|
||||||
|
) ?? null
|
||||||
|
);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
directives.find(directive =>
|
directives.find(directive =>
|
||||||
OPT_OUT_DIRECTIVES.has(directive.value.value),
|
OPT_OUT_DIRECTIVES.has(directive.value.value),
|
||||||
@@ -394,7 +403,8 @@ export function compileProgram(
|
|||||||
code: pass.code,
|
code: pass.code,
|
||||||
suppressions,
|
suppressions,
|
||||||
hasModuleScopeOptOut:
|
hasModuleScopeOptOut:
|
||||||
findDirectiveDisablingMemoization(program.node.directives) != null,
|
findDirectiveDisablingMemoization(program.node.directives, pass.opts) !=
|
||||||
|
null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const queue: Array<CompileSource> = findFunctionsToCompile(
|
const queue: Array<CompileSource> = findFunctionsToCompile(
|
||||||
@@ -571,7 +581,10 @@ function processFn(
|
|||||||
}
|
}
|
||||||
directives = {
|
directives = {
|
||||||
optIn: optIn.unwrapOr(null),
|
optIn: optIn.unwrapOr(null),
|
||||||
optOut: findDirectiveDisablingMemoization(fn.node.body.directives),
|
optOut: findDirectiveDisablingMemoization(
|
||||||
|
fn.node.body.directives,
|
||||||
|
programContext.opts,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,21 @@ const testComplexConfigDefaults: PartialEnvironmentConfig = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function* splitPragma(
|
||||||
|
pragma: string,
|
||||||
|
): Generator<{key: string; value: string | null}> {
|
||||||
|
for (const entry of pragma.split('@')) {
|
||||||
|
const keyVal = entry.trim();
|
||||||
|
const valIdx = keyVal.indexOf(':');
|
||||||
|
if (valIdx === -1) {
|
||||||
|
yield {key: keyVal.split(' ', 1)[0], value: null};
|
||||||
|
} else {
|
||||||
|
yield {key: keyVal.slice(0, valIdx), value: keyVal.slice(valIdx + 1)};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For snap test fixtures and playground only.
|
* For snap test fixtures and playground only.
|
||||||
*/
|
*/
|
||||||
@@ -101,19 +116,11 @@ function parseConfigPragmaEnvironmentForTest(
|
|||||||
): EnvironmentConfig {
|
): EnvironmentConfig {
|
||||||
const maybeConfig: Partial<Record<keyof EnvironmentConfig, unknown>> = {};
|
const maybeConfig: Partial<Record<keyof EnvironmentConfig, unknown>> = {};
|
||||||
|
|
||||||
for (const token of pragma.split(' ')) {
|
for (const {key, value: val} of splitPragma(pragma)) {
|
||||||
if (!token.startsWith('@')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const keyVal = token.slice(1);
|
|
||||||
const valIdx = keyVal.indexOf(':');
|
|
||||||
const key = valIdx === -1 ? keyVal : keyVal.slice(0, valIdx);
|
|
||||||
const val = valIdx === -1 ? undefined : keyVal.slice(valIdx + 1);
|
|
||||||
const isSet = val === undefined || val === 'true';
|
|
||||||
if (!hasOwnProperty(EnvironmentConfigSchema.shape, key)) {
|
if (!hasOwnProperty(EnvironmentConfigSchema.shape, key)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
const isSet = val == null || val === 'true';
|
||||||
if (isSet && key in testComplexConfigDefaults) {
|
if (isSet && key in testComplexConfigDefaults) {
|
||||||
maybeConfig[key] = testComplexConfigDefaults[key];
|
maybeConfig[key] = testComplexConfigDefaults[key];
|
||||||
} else if (isSet) {
|
} else if (isSet) {
|
||||||
@@ -176,18 +183,11 @@ export function parseConfigPragmaForTests(
|
|||||||
compilationMode: defaults.compilationMode,
|
compilationMode: defaults.compilationMode,
|
||||||
environment,
|
environment,
|
||||||
};
|
};
|
||||||
for (const token of pragma.split(' ')) {
|
for (const {key, value: val} of splitPragma(pragma)) {
|
||||||
if (!token.startsWith('@')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const keyVal = token.slice(1);
|
|
||||||
const idx = keyVal.indexOf(':');
|
|
||||||
const key = idx === -1 ? keyVal : keyVal.slice(0, idx);
|
|
||||||
const val = idx === -1 ? undefined : keyVal.slice(idx + 1);
|
|
||||||
if (!hasOwnProperty(defaultOptions, key)) {
|
if (!hasOwnProperty(defaultOptions, key)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const isSet = val === undefined || val === 'true';
|
const isSet = val == null || val === 'true';
|
||||||
if (isSet && key in testComplexPluginOptionDefaults) {
|
if (isSet && key in testComplexPluginOptionDefaults) {
|
||||||
options[key] = testComplexPluginOptionDefaults[key];
|
options[key] = testComplexPluginOptionDefaults[key];
|
||||||
} else if (isSet) {
|
} else if (isSet) {
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// @customOptOutDirectives:["use todo memo"]
|
||||||
|
function Component() {
|
||||||
|
'use todo memo';
|
||||||
|
return <div>hello world!</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// @customOptOutDirectives:["use todo memo"]
|
||||||
|
function Component() {
|
||||||
|
"use todo memo";
|
||||||
|
return <div>hello world!</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Eval output
|
||||||
|
(kind: ok) <div>hello world!</div>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// @customOptOutDirectives:["use todo memo"]
|
||||||
|
function Component() {
|
||||||
|
'use todo memo';
|
||||||
|
return <div>hello world!</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FIXTURE_ENTRYPOINT = {
|
||||||
|
fn: Component,
|
||||||
|
params: [],
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user