mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Merge c9cfbfda7e into sapling-pr-archive-poteto
This commit is contained in:
@@ -23,6 +23,7 @@ chrome-user-data
|
||||
.vscode
|
||||
*.swp
|
||||
*.swo
|
||||
*.vsix
|
||||
|
||||
packages/react-devtools-core/dist
|
||||
packages/react-devtools-extensions/chrome/build
|
||||
@@ -37,3 +38,4 @@ packages/react-devtools-fusebox/dist
|
||||
packages/react-devtools-inline/dist
|
||||
packages/react-devtools-shell/dist
|
||||
packages/react-devtools-timeline/dist
|
||||
|
||||
|
||||
@@ -26,11 +26,11 @@
|
||||
"react-is": "0.0.0-experimental-4beb1fd8-20241118"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-commonjs": "^28.0.2",
|
||||
"@rollup/plugin-json": "^6.1.0",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
"@rollup/plugin-node-resolve": "^16.0.0",
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@rollup/plugin-typescript": "^11.1.6",
|
||||
"@rollup/plugin-typescript": "^12.1.2",
|
||||
"@tsconfig/strictest": "^2.0.5",
|
||||
"concurrently": "^7.4.0",
|
||||
"folder-hash": "^4.0.4",
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
"babel-jest": "^29.0.3",
|
||||
"babel-plugin-fbt": "^1.0.0",
|
||||
"babel-plugin-fbt-runtime": "^1.0.0",
|
||||
"cosmiconfig": "^9.0.0",
|
||||
"eslint": "^8.57.1",
|
||||
"invariant": "^2.2.4",
|
||||
"jest": "^29.0.3",
|
||||
|
||||
@@ -15,7 +15,7 @@ import terser from '@rollup/plugin-terser';
|
||||
import prettier from 'rollup-plugin-prettier';
|
||||
import banner2 from 'rollup-plugin-banner2';
|
||||
|
||||
const NO_INLINE = new Set(['@babel/types']);
|
||||
const NO_INLINE = new Set([]);
|
||||
|
||||
const DEV_ROLLUP_CONFIG = {
|
||||
input: 'src/index.ts',
|
||||
@@ -24,6 +24,7 @@ const DEV_ROLLUP_CONFIG = {
|
||||
format: 'cjs',
|
||||
sourcemap: false,
|
||||
exports: 'named',
|
||||
inlineDynamicImports: true,
|
||||
},
|
||||
plugins: [
|
||||
typescript({
|
||||
|
||||
@@ -6,7 +6,12 @@
|
||||
*/
|
||||
|
||||
import type * as BabelCore from '@babel/core';
|
||||
import {compileProgram, parsePluginOptions} from '../Entrypoint';
|
||||
import {
|
||||
compileProgram,
|
||||
findReactConfig,
|
||||
parsePluginOptions,
|
||||
type PluginOptions,
|
||||
} from '../Entrypoint';
|
||||
import {
|
||||
injectReanimatedFlag,
|
||||
pipelineUsesReanimatedPlugin,
|
||||
@@ -29,7 +34,18 @@ export default function BabelPluginReactCompiler(
|
||||
* want Forget to run true to source as possible.
|
||||
*/
|
||||
Program(prog, pass): void {
|
||||
let opts = parsePluginOptions(pass.opts);
|
||||
const reactConfig = findReactConfig();
|
||||
let opts: PluginOptions | null = null;
|
||||
if (reactConfig != null) {
|
||||
opts = parsePluginOptions(reactConfig.config);
|
||||
if (pass.opts != null) {
|
||||
console.warn(
|
||||
`Duplicate React Compiler config found, defaulting to reactrc found in: ${reactConfig.filepath}`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
opts = parsePluginOptions(pass.opts);
|
||||
}
|
||||
const isDev =
|
||||
(typeof __DEV__ !== 'undefined' && __DEV__ === true) ||
|
||||
process.env['NODE_ENV'] === 'development';
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
import {hasOwnProperty} from '../Utils/utils';
|
||||
import {fromZodError} from 'zod-validation-error';
|
||||
import {CompilerPipelineValue} from './Pipeline';
|
||||
import {type CosmiconfigResult, cosmiconfigSync} from 'cosmiconfig';
|
||||
|
||||
const PanicThresholdOptionsSchema = z.enum([
|
||||
/*
|
||||
@@ -286,3 +287,11 @@ export function parseTargetConfig(value: unknown): CompilerReactTarget {
|
||||
function isCompilerFlag(s: string): s is keyof PluginOptions {
|
||||
return hasOwnProperty(defaultOptions, s);
|
||||
}
|
||||
|
||||
export function findReactConfig(): CosmiconfigResult {
|
||||
const explorerSync = cosmiconfigSync('react', {
|
||||
searchStrategy: 'project',
|
||||
cache: true,
|
||||
});
|
||||
return explorerSync.search();
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ import {validateNoJSXInTryStatement} from '../Validation/ValidateNoJSXInTryState
|
||||
import {propagateScopeDependenciesHIR} from '../HIR/PropagateScopeDependenciesHIR';
|
||||
import {outlineJSX} from '../Optimization/OutlineJsx';
|
||||
import {optimizePropsMethodCalls} from '../Optimization/OptimizePropsMethodCalls';
|
||||
import {transformFire} from '../Transform';
|
||||
|
||||
export type CompilerPipelineValue =
|
||||
| {kind: 'ast'; name: string; value: CodegenFunction}
|
||||
@@ -197,6 +198,11 @@ function runWithEnvironment(
|
||||
validateHooksUsage(hir);
|
||||
}
|
||||
|
||||
if (env.config.enableFire) {
|
||||
transformFire(hir);
|
||||
log({kind: 'hir', name: 'TransformFire', value: hir});
|
||||
}
|
||||
|
||||
if (env.config.validateNoCapitalizedCalls) {
|
||||
validateNoCapitalizedCalls(hir);
|
||||
}
|
||||
|
||||
@@ -564,6 +564,14 @@ export function compileProgram(
|
||||
if (environment.enableChangeDetectionForDebugging != null) {
|
||||
externalFunctions.push(environment.enableChangeDetectionForDebugging);
|
||||
}
|
||||
|
||||
const hasFireRewrite = compiledFns.some(c => c.compiledFn.hasFireRewrite);
|
||||
if (environment.enableFire && hasFireRewrite) {
|
||||
externalFunctions.push({
|
||||
source: getReactCompilerRuntimeModule(pass.opts),
|
||||
importSpecifierName: 'useFire',
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
handleError(err, pass, null);
|
||||
return;
|
||||
|
||||
@@ -787,6 +787,7 @@ export class Environment {
|
||||
fnType: ReactFunctionType;
|
||||
useMemoCacheIdentifier: string;
|
||||
hasLoweredContextAccess: boolean;
|
||||
hasFireRewrite: boolean;
|
||||
|
||||
#contextIdentifiers: Set<t.Identifier>;
|
||||
#hoistedIdentifiers: Set<t.Identifier>;
|
||||
@@ -811,6 +812,7 @@ export class Environment {
|
||||
this.#shapes = new Map(DEFAULT_SHAPES);
|
||||
this.#globals = new Map(DEFAULT_GLOBALS);
|
||||
this.hasLoweredContextAccess = false;
|
||||
this.hasFireRewrite = false;
|
||||
|
||||
if (
|
||||
config.disableMemoizationForDebugging &&
|
||||
|
||||
@@ -897,6 +897,14 @@ export function printSourceLocation(loc: SourceLocation): string {
|
||||
}
|
||||
}
|
||||
|
||||
export function printSourceLocationLine(loc: SourceLocation): string {
|
||||
if (typeof loc === 'symbol') {
|
||||
return 'generated';
|
||||
} else {
|
||||
return `${loc.start.line}:${loc.end.line}`;
|
||||
}
|
||||
}
|
||||
|
||||
export function printAliases(aliases: DisjointSet<Identifier>): string {
|
||||
const aliasSets = aliases.buildSets();
|
||||
|
||||
|
||||
+6
@@ -103,6 +103,11 @@ export type CodegenFunction = {
|
||||
* This is true if the compiler has the lowered useContext calls.
|
||||
*/
|
||||
hasLoweredContextAccess: boolean;
|
||||
|
||||
/**
|
||||
* This is true if the compiler has compiled a fire to a useFire call
|
||||
*/
|
||||
hasFireRewrite: boolean;
|
||||
};
|
||||
|
||||
export function codegenFunction(
|
||||
@@ -355,6 +360,7 @@ function codegenReactiveFunction(
|
||||
prunedMemoValues: countMemoBlockVisitor.prunedMemoValues,
|
||||
outlined: [],
|
||||
hasLoweredContextAccess: fn.env.hasLoweredContextAccess,
|
||||
hasFireRewrite: fn.env.hasFireRewrite,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,760 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {
|
||||
CompilerError,
|
||||
CompilerErrorDetailOptions,
|
||||
ErrorSeverity,
|
||||
SourceLocation,
|
||||
} from '..';
|
||||
import {
|
||||
ArrayExpression,
|
||||
CallExpression,
|
||||
Effect,
|
||||
Environment,
|
||||
FunctionExpression,
|
||||
GeneratedSource,
|
||||
HIRFunction,
|
||||
Identifier,
|
||||
IdentifierId,
|
||||
Instruction,
|
||||
InstructionId,
|
||||
InstructionKind,
|
||||
InstructionValue,
|
||||
isUseEffectHookType,
|
||||
LoadLocal,
|
||||
makeInstructionId,
|
||||
Place,
|
||||
promoteTemporary,
|
||||
} from '../HIR';
|
||||
import {createTemporaryPlace, markInstructionIds} from '../HIR/HIRBuilder';
|
||||
import {getOrInsertWith} from '../Utils/utils';
|
||||
import {BuiltInFireId, DefaultNonmutatingHook} from '../HIR/ObjectShape';
|
||||
import {eachInstructionOperand} from '../HIR/visitors';
|
||||
import {printSourceLocationLine} from '../HIR/PrintHIR';
|
||||
|
||||
/*
|
||||
* TODO(jmbrown):
|
||||
* - traverse object methods
|
||||
* - method calls
|
||||
* - React.useEffect calls
|
||||
*/
|
||||
|
||||
const CANNOT_COMPILE_FIRE = 'Cannot compile `fire`';
|
||||
|
||||
export function transformFire(fn: HIRFunction): void {
|
||||
const context = new Context(fn.env);
|
||||
replaceFireFunctions(fn, context);
|
||||
if (!context.hasErrors()) {
|
||||
ensureNoMoreFireUses(fn, context);
|
||||
}
|
||||
context.throwIfErrorsFound();
|
||||
}
|
||||
|
||||
function replaceFireFunctions(fn: HIRFunction, context: Context): void {
|
||||
let hasRewrite = false;
|
||||
for (const [, block] of fn.body.blocks) {
|
||||
const rewriteInstrs = new Map<InstructionId, Array<Instruction>>();
|
||||
const deleteInstrs = new Set<InstructionId>();
|
||||
for (const instr of block.instructions) {
|
||||
const {value, lvalue} = instr;
|
||||
if (
|
||||
value.kind === 'CallExpression' &&
|
||||
isUseEffectHookType(value.callee.identifier) &&
|
||||
value.args.length > 0 &&
|
||||
value.args[0].kind === 'Identifier'
|
||||
) {
|
||||
const lambda = context.getFunctionExpression(
|
||||
value.args[0].identifier.id,
|
||||
);
|
||||
if (lambda != null) {
|
||||
const capturedCallees =
|
||||
visitFunctionExpressionAndPropagateFireDependencies(
|
||||
lambda,
|
||||
context,
|
||||
true,
|
||||
);
|
||||
|
||||
// Add useFire calls for all fire calls in found in the lambda
|
||||
const newInstrs = [];
|
||||
for (const [
|
||||
fireCalleePlace,
|
||||
fireCalleeInfo,
|
||||
] of capturedCallees.entries()) {
|
||||
if (!context.hasCalleeWithInsertedFire(fireCalleePlace)) {
|
||||
context.addCalleeWithInsertedFire(fireCalleePlace);
|
||||
const loadUseFireInstr = makeLoadUseFireInstruction(fn.env);
|
||||
const loadFireCalleeInstr = makeLoadFireCalleeInstruction(
|
||||
fn.env,
|
||||
fireCalleeInfo.capturedCalleeIdentifier,
|
||||
);
|
||||
const callUseFireInstr = makeCallUseFireInstruction(
|
||||
fn.env,
|
||||
loadUseFireInstr.lvalue,
|
||||
loadFireCalleeInstr.lvalue,
|
||||
);
|
||||
const storeUseFireInstr = makeStoreUseFireInstruction(
|
||||
fn.env,
|
||||
callUseFireInstr.lvalue,
|
||||
fireCalleeInfo.fireFunctionBinding,
|
||||
);
|
||||
newInstrs.push(
|
||||
loadUseFireInstr,
|
||||
loadFireCalleeInstr,
|
||||
callUseFireInstr,
|
||||
storeUseFireInstr,
|
||||
);
|
||||
|
||||
// We insert all of these instructions before the useEffect is loaded
|
||||
const loadUseEffectInstrId = context.getLoadGlobalInstrId(
|
||||
value.callee.identifier.id,
|
||||
);
|
||||
if (loadUseEffectInstrId == null) {
|
||||
context.pushError({
|
||||
loc: value.loc,
|
||||
description: null,
|
||||
severity: ErrorSeverity.Invariant,
|
||||
reason: '[InsertFire] No LoadGlobal found for useEffect call',
|
||||
suggestions: null,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
rewriteInstrs.set(loadUseEffectInstrId, newInstrs);
|
||||
}
|
||||
}
|
||||
ensureNoRemainingCalleeCaptures(
|
||||
lambda.loweredFunc.func,
|
||||
context,
|
||||
capturedCallees,
|
||||
);
|
||||
|
||||
if (
|
||||
value.args.length > 1 &&
|
||||
value.args[1] != null &&
|
||||
value.args[1].kind === 'Identifier'
|
||||
) {
|
||||
const depArray = value.args[1];
|
||||
const depArrayExpression = context.getArrayExpression(
|
||||
depArray.identifier.id,
|
||||
);
|
||||
if (depArrayExpression != null) {
|
||||
for (const dependency of depArrayExpression.elements) {
|
||||
if (dependency.kind === 'Identifier') {
|
||||
const loadOfDependency = context.getLoadLocalInstr(
|
||||
dependency.identifier.id,
|
||||
);
|
||||
if (loadOfDependency != null) {
|
||||
const replacedDepArrayItem = capturedCallees.get(
|
||||
loadOfDependency.place.identifier.id,
|
||||
);
|
||||
if (replacedDepArrayItem != null) {
|
||||
loadOfDependency.place =
|
||||
replacedDepArrayItem.fireFunctionBinding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
context.pushError({
|
||||
loc: value.args[1].loc,
|
||||
description:
|
||||
'You must use an array literal for an effect dependency array when that effect uses `fire()`',
|
||||
severity: ErrorSeverity.Invariant,
|
||||
reason: CANNOT_COMPILE_FIRE,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
} else if (value.args.length > 1 && value.args[1].kind === 'Spread') {
|
||||
context.pushError({
|
||||
loc: value.args[1].place.loc,
|
||||
description:
|
||||
'You must use an array literal for an effect dependency array when that effect uses `fire()`',
|
||||
severity: ErrorSeverity.Invariant,
|
||||
reason: CANNOT_COMPILE_FIRE,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
value.kind === 'CallExpression' &&
|
||||
value.callee.identifier.type.kind === 'Function' &&
|
||||
value.callee.identifier.type.shapeId === BuiltInFireId &&
|
||||
context.inUseEffectLambda()
|
||||
) {
|
||||
/*
|
||||
* We found a fire(callExpr()) call. We remove the `fire()` call and replace the callExpr()
|
||||
* with a freshly generated fire function binding. We'll insert the useFire call before the
|
||||
* useEffect call, which happens in the CallExpression (useEffect) case above.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We only allow fire to be called with a CallExpression: `fire(f())`
|
||||
* TODO: add support for method calls: `fire(this.method())`
|
||||
*/
|
||||
if (value.args.length === 1 && value.args[0].kind === 'Identifier') {
|
||||
const callExpr = context.getCallExpression(
|
||||
value.args[0].identifier.id,
|
||||
);
|
||||
|
||||
if (callExpr != null) {
|
||||
const calleeId = callExpr.callee.identifier.id;
|
||||
const loadLocal = context.getLoadLocalInstr(calleeId);
|
||||
if (loadLocal == null) {
|
||||
context.pushError({
|
||||
loc: value.loc,
|
||||
description: null,
|
||||
severity: ErrorSeverity.Invariant,
|
||||
reason:
|
||||
'[InsertFire] No loadLocal found for fire call argument',
|
||||
suggestions: null,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const fireFunctionBinding =
|
||||
context.getOrGenerateFireFunctionBinding(
|
||||
loadLocal.place,
|
||||
value.loc,
|
||||
);
|
||||
|
||||
loadLocal.place = {...fireFunctionBinding};
|
||||
|
||||
// Delete the fire call expression
|
||||
deleteInstrs.add(instr.id);
|
||||
} else {
|
||||
context.pushError({
|
||||
loc: value.loc,
|
||||
description:
|
||||
'`fire()` can only receive a function call such as `fire(fn(a,b)). Method calls and other expressions are not allowed',
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
reason: CANNOT_COMPILE_FIRE,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
let description: string =
|
||||
'fire() can only take in a single call expression as an argument';
|
||||
if (value.args.length === 0) {
|
||||
description += ' but received none';
|
||||
} else if (value.args.length > 1) {
|
||||
description += ' but received multiple arguments';
|
||||
} else if (value.args[0].kind === 'Spread') {
|
||||
description += ' but received a spread argument';
|
||||
}
|
||||
context.pushError({
|
||||
loc: value.loc,
|
||||
description,
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
reason: CANNOT_COMPILE_FIRE,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
} else if (value.kind === 'CallExpression') {
|
||||
context.addCallExpression(lvalue.identifier.id, value);
|
||||
} else if (
|
||||
value.kind === 'FunctionExpression' &&
|
||||
context.inUseEffectLambda()
|
||||
) {
|
||||
visitFunctionExpressionAndPropagateFireDependencies(
|
||||
value,
|
||||
context,
|
||||
false,
|
||||
);
|
||||
} else if (value.kind === 'FunctionExpression') {
|
||||
context.addFunctionExpression(lvalue.identifier.id, value);
|
||||
} else if (value.kind === 'LoadLocal') {
|
||||
context.addLoadLocalInstr(lvalue.identifier.id, value);
|
||||
} else if (
|
||||
value.kind === 'LoadGlobal' &&
|
||||
value.binding.kind === 'ImportSpecifier' &&
|
||||
value.binding.module === 'react' &&
|
||||
value.binding.imported === 'fire' &&
|
||||
context.inUseEffectLambda()
|
||||
) {
|
||||
deleteInstrs.add(instr.id);
|
||||
} else if (value.kind === 'LoadGlobal') {
|
||||
context.addLoadGlobalInstrId(lvalue.identifier.id, instr.id);
|
||||
} else if (value.kind === 'ArrayExpression') {
|
||||
context.addArrayExpression(lvalue.identifier.id, value);
|
||||
}
|
||||
}
|
||||
block.instructions = rewriteInstructions(rewriteInstrs, block.instructions);
|
||||
block.instructions = deleteInstructions(deleteInstrs, block.instructions);
|
||||
|
||||
if (rewriteInstrs.size > 0 || deleteInstrs.size > 0) {
|
||||
hasRewrite = true;
|
||||
fn.env.hasFireRewrite = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasRewrite) {
|
||||
markInstructionIds(fn.body);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses a function expression to find fire calls fire(foo()) and replaces them with
|
||||
* fireFoo().
|
||||
*
|
||||
* When a function captures a fire call we need to update its context to reflect the newly created
|
||||
* fire function bindings and update the LoadLocals referenced by the function's dependencies.
|
||||
*
|
||||
* @param isUseEffect is necessary so we can keep track of when we should additionally insert
|
||||
* useFire hooks calls.
|
||||
*/
|
||||
function visitFunctionExpressionAndPropagateFireDependencies(
|
||||
fnExpr: FunctionExpression,
|
||||
context: Context,
|
||||
enteringUseEffect: boolean,
|
||||
): FireCalleesToFireFunctionBinding {
|
||||
let withScope = enteringUseEffect
|
||||
? context.withUseEffectLambdaScope.bind(context)
|
||||
: context.withFunctionScope.bind(context);
|
||||
|
||||
const calleesCapturedByFnExpression = withScope(() =>
|
||||
replaceFireFunctions(fnExpr.loweredFunc.func, context),
|
||||
);
|
||||
|
||||
/*
|
||||
* Make a mapping from each dependency to the corresponding LoadLocal for it so that
|
||||
* we can replace the loaded place with the generated fire function binding
|
||||
*/
|
||||
const loadLocalsToDepLoads = new Map<IdentifierId, LoadLocal>();
|
||||
for (const dep of fnExpr.loweredFunc.dependencies) {
|
||||
const loadLocal = context.getLoadLocalInstr(dep.identifier.id);
|
||||
if (loadLocal != null) {
|
||||
loadLocalsToDepLoads.set(loadLocal.place.identifier.id, loadLocal);
|
||||
}
|
||||
}
|
||||
|
||||
const replacedCallees = new Map<IdentifierId, Place>();
|
||||
for (const [
|
||||
calleeIdentifierId,
|
||||
loadedFireFunctionBindingPlace,
|
||||
] of calleesCapturedByFnExpression.entries()) {
|
||||
/*
|
||||
* Given the ids of captured fire callees, look at the deps for loads of those identifiers
|
||||
* and replace them with the new fire function binding
|
||||
*/
|
||||
const loadLocal = loadLocalsToDepLoads.get(calleeIdentifierId);
|
||||
if (loadLocal == null) {
|
||||
context.pushError({
|
||||
loc: fnExpr.loc,
|
||||
description: null,
|
||||
severity: ErrorSeverity.Invariant,
|
||||
reason:
|
||||
'[InsertFire] No loadLocal found for fire call argument for lambda',
|
||||
suggestions: null,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const oldPlaceId = loadLocal.place.identifier.id;
|
||||
loadLocal.place = {
|
||||
...loadedFireFunctionBindingPlace.fireFunctionBinding,
|
||||
};
|
||||
|
||||
replacedCallees.set(
|
||||
oldPlaceId,
|
||||
loadedFireFunctionBindingPlace.fireFunctionBinding,
|
||||
);
|
||||
}
|
||||
|
||||
// For each replaced callee, update the context of the function expression to track it
|
||||
for (
|
||||
let contextIdx = 0;
|
||||
contextIdx < fnExpr.loweredFunc.func.context.length;
|
||||
contextIdx++
|
||||
) {
|
||||
const contextItem = fnExpr.loweredFunc.func.context[contextIdx];
|
||||
const replacedCallee = replacedCallees.get(contextItem.identifier.id);
|
||||
if (replacedCallee != null) {
|
||||
fnExpr.loweredFunc.func.context[contextIdx] = replacedCallee;
|
||||
}
|
||||
}
|
||||
|
||||
context.mergeCalleesFromInnerScope(calleesCapturedByFnExpression);
|
||||
|
||||
return calleesCapturedByFnExpression;
|
||||
}
|
||||
|
||||
/*
|
||||
* eachInstructionOperand is not sufficient for our cases because:
|
||||
* 1. fire is a global, which will not appear
|
||||
* 2. The HIR may be malformed, so can't rely on function deps and must
|
||||
* traverse the whole function.
|
||||
*/
|
||||
function* eachReachablePlace(fn: HIRFunction): Iterable<Place> {
|
||||
for (const [, block] of fn.body.blocks) {
|
||||
for (const instr of block.instructions) {
|
||||
if (
|
||||
instr.value.kind === 'FunctionExpression' ||
|
||||
instr.value.kind === 'ObjectMethod'
|
||||
) {
|
||||
yield* eachReachablePlace(instr.value.loweredFunc.func);
|
||||
} else {
|
||||
yield* eachInstructionOperand(instr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ensureNoRemainingCalleeCaptures(
|
||||
fn: HIRFunction,
|
||||
context: Context,
|
||||
capturedCallees: FireCalleesToFireFunctionBinding,
|
||||
): void {
|
||||
for (const place of eachReachablePlace(fn)) {
|
||||
const calleeInfo = capturedCallees.get(place.identifier.id);
|
||||
if (calleeInfo != null) {
|
||||
const calleeName =
|
||||
calleeInfo.capturedCalleeIdentifier.name?.kind === 'named'
|
||||
? calleeInfo.capturedCalleeIdentifier.name.value
|
||||
: '<unknown>';
|
||||
context.pushError({
|
||||
loc: place.loc,
|
||||
description: `All uses of ${calleeName} must be either used with a fire() call in \
|
||||
this effect or not used with a fire() call at all. ${calleeName} was used with fire() on line \
|
||||
${printSourceLocationLine(calleeInfo.fireLoc)} in this effect`,
|
||||
severity: ErrorSeverity.InvalidReact,
|
||||
reason: CANNOT_COMPILE_FIRE,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ensureNoMoreFireUses(fn: HIRFunction, context: Context): void {
|
||||
for (const place of eachReachablePlace(fn)) {
|
||||
if (
|
||||
place.identifier.type.kind === 'Function' &&
|
||||
place.identifier.type.shapeId === BuiltInFireId
|
||||
) {
|
||||
context.pushError({
|
||||
loc: place.identifier.loc,
|
||||
description: 'Cannot use `fire` outside of a useEffect function',
|
||||
severity: ErrorSeverity.Invariant,
|
||||
reason: CANNOT_COMPILE_FIRE,
|
||||
suggestions: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeLoadUseFireInstruction(env: Environment): Instruction {
|
||||
const useFirePlace = createTemporaryPlace(env, GeneratedSource);
|
||||
useFirePlace.effect = Effect.Read;
|
||||
useFirePlace.identifier.type = DefaultNonmutatingHook;
|
||||
const instrValue: InstructionValue = {
|
||||
kind: 'LoadGlobal',
|
||||
binding: {
|
||||
kind: 'ImportSpecifier',
|
||||
name: 'useFire',
|
||||
module: 'react',
|
||||
imported: 'useFire',
|
||||
},
|
||||
loc: GeneratedSource,
|
||||
};
|
||||
return {
|
||||
id: makeInstructionId(0),
|
||||
value: instrValue,
|
||||
lvalue: {...useFirePlace},
|
||||
loc: GeneratedSource,
|
||||
};
|
||||
}
|
||||
|
||||
function makeLoadFireCalleeInstruction(
|
||||
env: Environment,
|
||||
fireCalleeIdentifier: Identifier,
|
||||
): Instruction {
|
||||
const loadedFireCallee = createTemporaryPlace(env, GeneratedSource);
|
||||
const fireCallee: Place = {
|
||||
kind: 'Identifier',
|
||||
identifier: fireCalleeIdentifier,
|
||||
reactive: false,
|
||||
effect: Effect.Unknown,
|
||||
loc: fireCalleeIdentifier.loc,
|
||||
};
|
||||
return {
|
||||
id: makeInstructionId(0),
|
||||
value: {
|
||||
kind: 'LoadLocal',
|
||||
loc: GeneratedSource,
|
||||
place: {...fireCallee},
|
||||
},
|
||||
lvalue: {...loadedFireCallee},
|
||||
loc: GeneratedSource,
|
||||
};
|
||||
}
|
||||
|
||||
function makeCallUseFireInstruction(
|
||||
env: Environment,
|
||||
useFirePlace: Place,
|
||||
argPlace: Place,
|
||||
): Instruction {
|
||||
const useFireCallResultPlace = createTemporaryPlace(env, GeneratedSource);
|
||||
useFireCallResultPlace.effect = Effect.Read;
|
||||
|
||||
const useFireCall: CallExpression = {
|
||||
kind: 'CallExpression',
|
||||
callee: {...useFirePlace},
|
||||
args: [argPlace],
|
||||
loc: GeneratedSource,
|
||||
};
|
||||
|
||||
return {
|
||||
id: makeInstructionId(0),
|
||||
value: useFireCall,
|
||||
lvalue: {...useFireCallResultPlace},
|
||||
loc: GeneratedSource,
|
||||
};
|
||||
}
|
||||
|
||||
function makeStoreUseFireInstruction(
|
||||
env: Environment,
|
||||
useFireCallResultPlace: Place,
|
||||
fireFunctionBindingPlace: Place,
|
||||
): Instruction {
|
||||
promoteTemporary(fireFunctionBindingPlace.identifier);
|
||||
|
||||
const fireFunctionBindingLValuePlace = createTemporaryPlace(
|
||||
env,
|
||||
GeneratedSource,
|
||||
);
|
||||
return {
|
||||
id: makeInstructionId(0),
|
||||
value: {
|
||||
kind: 'StoreLocal',
|
||||
lvalue: {
|
||||
kind: InstructionKind.Const,
|
||||
place: {...fireFunctionBindingPlace},
|
||||
},
|
||||
value: {...useFireCallResultPlace},
|
||||
type: null,
|
||||
loc: GeneratedSource,
|
||||
},
|
||||
lvalue: fireFunctionBindingLValuePlace,
|
||||
loc: GeneratedSource,
|
||||
};
|
||||
}
|
||||
|
||||
type FireCalleesToFireFunctionBinding = Map<
|
||||
IdentifierId,
|
||||
{
|
||||
fireFunctionBinding: Place;
|
||||
capturedCalleeIdentifier: Identifier;
|
||||
fireLoc: SourceLocation;
|
||||
}
|
||||
>;
|
||||
|
||||
class Context {
|
||||
#env: Environment;
|
||||
|
||||
#errors: CompilerError = new CompilerError();
|
||||
|
||||
/*
|
||||
* Used to look up the call expression passed to a `fire(callExpr())`. Gives back
|
||||
* the `callExpr()`.
|
||||
*/
|
||||
#callExpressions = new Map<IdentifierId, CallExpression>();
|
||||
|
||||
/*
|
||||
* We keep track of function expressions so that we can traverse them when
|
||||
* we encounter a lambda passed to a useEffect call
|
||||
*/
|
||||
#functionExpressions = new Map<IdentifierId, FunctionExpression>();
|
||||
|
||||
/*
|
||||
* Mapping from lvalue ids to the LoadLocal for it. Allows us to replace dependency LoadLocals.
|
||||
*/
|
||||
#loadLocals = new Map<IdentifierId, LoadLocal>();
|
||||
|
||||
/*
|
||||
* Maps all of the fire callees found in a component/hook to the generated fire function places
|
||||
* we create for them. Allows us to reuse already-inserted useFire results
|
||||
*/
|
||||
#fireCalleesToFireFunctions: Map<IdentifierId, Place> = new Map();
|
||||
|
||||
/*
|
||||
* The callees for which we have already created fire bindings. Used to skip inserting a new
|
||||
* useFire call for a fire callee if one has already been created.
|
||||
*/
|
||||
#calleesWithInsertedFire = new Set<IdentifierId>();
|
||||
|
||||
/*
|
||||
* A mapping from fire callees to the created fire function bindings that are reachable from this
|
||||
* scope.
|
||||
*
|
||||
* We additionally keep track of the captured callee identifier so that we can properly reference
|
||||
* it in the place where we LoadLocal the callee as an argument to useFire.
|
||||
*/
|
||||
#capturedCalleeIdentifierIds: FireCalleesToFireFunctionBinding = new Map();
|
||||
|
||||
/*
|
||||
* We only transform fire calls if we're syntactically within a useEffect lambda (for now)
|
||||
*/
|
||||
#inUseEffectLambda = false;
|
||||
|
||||
/*
|
||||
* Mapping from useEffect callee identifier ids to the instruction id of the
|
||||
* load global instruction for the useEffect call. We use this to insert the
|
||||
* useFire calls before the useEffect call
|
||||
*/
|
||||
#loadGlobalInstructionIds = new Map<IdentifierId, InstructionId>();
|
||||
|
||||
constructor(env: Environment) {
|
||||
this.#env = env;
|
||||
}
|
||||
|
||||
/*
|
||||
* We keep track of array expressions so we can rewrite dependency arrays passed to useEffect
|
||||
* to use the fire functions
|
||||
*/
|
||||
#arrayExpressions = new Map<IdentifierId, ArrayExpression>();
|
||||
|
||||
pushError(error: CompilerErrorDetailOptions): void {
|
||||
this.#errors.push(error);
|
||||
}
|
||||
|
||||
withFunctionScope(fn: () => void): FireCalleesToFireFunctionBinding {
|
||||
fn();
|
||||
return this.#capturedCalleeIdentifierIds;
|
||||
}
|
||||
|
||||
withUseEffectLambdaScope(fn: () => void): FireCalleesToFireFunctionBinding {
|
||||
const capturedCalleeIdentifierIds = this.#capturedCalleeIdentifierIds;
|
||||
const inUseEffectLambda = this.#inUseEffectLambda;
|
||||
|
||||
this.#capturedCalleeIdentifierIds = new Map();
|
||||
this.#inUseEffectLambda = true;
|
||||
|
||||
const resultCapturedCalleeIdentifierIds = this.withFunctionScope(fn);
|
||||
|
||||
this.#capturedCalleeIdentifierIds = capturedCalleeIdentifierIds;
|
||||
this.#inUseEffectLambda = inUseEffectLambda;
|
||||
|
||||
return resultCapturedCalleeIdentifierIds;
|
||||
}
|
||||
|
||||
addCallExpression(id: IdentifierId, callExpr: CallExpression): void {
|
||||
this.#callExpressions.set(id, callExpr);
|
||||
}
|
||||
|
||||
getCallExpression(id: IdentifierId): CallExpression | undefined {
|
||||
return this.#callExpressions.get(id);
|
||||
}
|
||||
|
||||
addLoadLocalInstr(id: IdentifierId, loadLocal: LoadLocal): void {
|
||||
this.#loadLocals.set(id, loadLocal);
|
||||
}
|
||||
|
||||
getLoadLocalInstr(id: IdentifierId): LoadLocal | undefined {
|
||||
return this.#loadLocals.get(id);
|
||||
}
|
||||
getOrGenerateFireFunctionBinding(
|
||||
callee: Place,
|
||||
fireLoc: SourceLocation,
|
||||
): Place {
|
||||
const fireFunctionBinding = getOrInsertWith(
|
||||
this.#fireCalleesToFireFunctions,
|
||||
callee.identifier.id,
|
||||
() => createTemporaryPlace(this.#env, GeneratedSource),
|
||||
);
|
||||
|
||||
this.#capturedCalleeIdentifierIds.set(callee.identifier.id, {
|
||||
fireFunctionBinding,
|
||||
capturedCalleeIdentifier: callee.identifier,
|
||||
fireLoc,
|
||||
});
|
||||
|
||||
return fireFunctionBinding;
|
||||
}
|
||||
|
||||
mergeCalleesFromInnerScope(
|
||||
innerCallees: FireCalleesToFireFunctionBinding,
|
||||
): void {
|
||||
for (const [id, calleeInfo] of innerCallees.entries()) {
|
||||
this.#capturedCalleeIdentifierIds.set(id, calleeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
addCalleeWithInsertedFire(id: IdentifierId): void {
|
||||
this.#calleesWithInsertedFire.add(id);
|
||||
}
|
||||
|
||||
hasCalleeWithInsertedFire(id: IdentifierId): boolean {
|
||||
return this.#calleesWithInsertedFire.has(id);
|
||||
}
|
||||
|
||||
inUseEffectLambda(): boolean {
|
||||
return this.#inUseEffectLambda;
|
||||
}
|
||||
|
||||
addFunctionExpression(id: IdentifierId, fn: FunctionExpression): void {
|
||||
this.#functionExpressions.set(id, fn);
|
||||
}
|
||||
|
||||
getFunctionExpression(id: IdentifierId): FunctionExpression | undefined {
|
||||
return this.#functionExpressions.get(id);
|
||||
}
|
||||
|
||||
addLoadGlobalInstrId(id: IdentifierId, instrId: InstructionId): void {
|
||||
this.#loadGlobalInstructionIds.set(id, instrId);
|
||||
}
|
||||
|
||||
getLoadGlobalInstrId(id: IdentifierId): InstructionId | undefined {
|
||||
return this.#loadGlobalInstructionIds.get(id);
|
||||
}
|
||||
|
||||
addArrayExpression(id: IdentifierId, array: ArrayExpression): void {
|
||||
this.#arrayExpressions.set(id, array);
|
||||
}
|
||||
|
||||
getArrayExpression(id: IdentifierId): ArrayExpression | undefined {
|
||||
return this.#arrayExpressions.get(id);
|
||||
}
|
||||
|
||||
hasErrors(): boolean {
|
||||
return this.#errors.hasErrors();
|
||||
}
|
||||
|
||||
throwIfErrorsFound(): void {
|
||||
if (this.hasErrors()) throw this.#errors;
|
||||
}
|
||||
}
|
||||
|
||||
function deleteInstructions(
|
||||
deleteInstrs: Set<InstructionId>,
|
||||
instructions: Array<Instruction>,
|
||||
): Array<Instruction> {
|
||||
if (deleteInstrs.size > 0) {
|
||||
const newInstrs = instructions.filter(instr => !deleteInstrs.has(instr.id));
|
||||
return newInstrs;
|
||||
}
|
||||
return instructions;
|
||||
}
|
||||
|
||||
function rewriteInstructions(
|
||||
rewriteInstrs: Map<InstructionId, Array<Instruction>>,
|
||||
instructions: Array<Instruction>,
|
||||
): Array<Instruction> {
|
||||
if (rewriteInstrs.size > 0) {
|
||||
const newInstrs = [];
|
||||
for (const instr of instructions) {
|
||||
const newInstrsAtId = rewriteInstrs.get(instr.id);
|
||||
if (newInstrsAtId != null) {
|
||||
newInstrs.push(...newInstrsAtId, instr);
|
||||
} else {
|
||||
newInstrs.push(instr);
|
||||
}
|
||||
}
|
||||
|
||||
return newInstrs;
|
||||
}
|
||||
|
||||
return instructions;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
export {transformFire} from './TransformFire';
|
||||
+8
@@ -305,6 +305,14 @@ function validateNoRefAccessInRenderImpl(
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'TypeCastExpression': {
|
||||
env.set(
|
||||
instr.lvalue.identifier.id,
|
||||
env.get(instr.value.value.identifier.id) ??
|
||||
refTypeOfType(instr.lvalue),
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'LoadContext':
|
||||
case 'LoadLocal': {
|
||||
env.set(
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import {useRef} from 'react';
|
||||
|
||||
function useArrayOfRef() {
|
||||
const ref = useRef(null);
|
||||
const callback = value => {
|
||||
ref.current = value;
|
||||
};
|
||||
return [callback] as const;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: () => {
|
||||
useArrayOfRef();
|
||||
return 'ok';
|
||||
},
|
||||
params: [{}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime";
|
||||
import { useRef } from "react";
|
||||
|
||||
function useArrayOfRef() {
|
||||
const $ = _c(1);
|
||||
const ref = useRef(null);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
const callback = (value) => {
|
||||
ref.current = value;
|
||||
};
|
||||
|
||||
t0 = [callback];
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
return t0 as const;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: () => {
|
||||
useArrayOfRef();
|
||||
return "ok";
|
||||
},
|
||||
|
||||
params: [{}],
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: ok) "ok"
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import {useRef} from 'react';
|
||||
|
||||
function useArrayOfRef() {
|
||||
const ref = useRef(null);
|
||||
const callback = value => {
|
||||
ref.current = value;
|
||||
};
|
||||
return [callback] as const;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: () => {
|
||||
useArrayOfRef();
|
||||
return 'ok';
|
||||
},
|
||||
params: [{}],
|
||||
};
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { useFire } from "react/compiler-runtime";
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableFire
|
||||
import { fire } from "react";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(3);
|
||||
const foo = _temp;
|
||||
const t0 = useFire(foo);
|
||||
let t1;
|
||||
if ($[0] !== props || $[1] !== t0) {
|
||||
t1 = () => {
|
||||
t0(props);
|
||||
};
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
$[2] = t1;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
}
|
||||
useEffect(t1);
|
||||
return null;
|
||||
}
|
||||
function _temp(props_0) {
|
||||
console.log(props_0);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Fixture not implemented
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
function nested() {
|
||||
function nestedAgain() {
|
||||
function nestedThrice() {
|
||||
fire(foo(props));
|
||||
}
|
||||
nestedThrice();
|
||||
}
|
||||
nestedAgain();
|
||||
}
|
||||
nested();
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { useFire } from "react/compiler-runtime";
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableFire
|
||||
import { fire } from "react";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(3);
|
||||
const foo = _temp;
|
||||
const t0 = useFire(foo);
|
||||
let t1;
|
||||
if ($[0] !== props || $[1] !== t0) {
|
||||
t1 = () => {
|
||||
const nested = function nested() {
|
||||
const nestedAgain = function nestedAgain() {
|
||||
const nestedThrice = function nestedThrice() {
|
||||
t0(props);
|
||||
};
|
||||
|
||||
nestedThrice();
|
||||
};
|
||||
|
||||
nestedAgain();
|
||||
};
|
||||
|
||||
nested();
|
||||
};
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
$[2] = t1;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
}
|
||||
useEffect(t1);
|
||||
return null;
|
||||
}
|
||||
function _temp(props_0) {
|
||||
console.log(props_0);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Fixture not implemented
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
function nested() {
|
||||
function nestedAgain() {
|
||||
function nestedThrice() {
|
||||
fire(foo(props));
|
||||
}
|
||||
nestedThrice();
|
||||
}
|
||||
nestedAgain();
|
||||
}
|
||||
nested();
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire, useEffect} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
|
||||
if (props.cond) {
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
8 |
|
||||
9 | if (props.cond) {
|
||||
> 10 | useEffect(() => {
|
||||
| ^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (10:10)
|
||||
11 | fire(foo(props));
|
||||
12 | });
|
||||
13 | }
|
||||
```
|
||||
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// @enableFire
|
||||
import {fire, useEffect} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
|
||||
if (props.cond) {
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
function nested() {
|
||||
fire(foo(props));
|
||||
foo(props);
|
||||
}
|
||||
|
||||
nested();
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
9 | function nested() {
|
||||
10 | fire(foo(props));
|
||||
> 11 | foo(props);
|
||||
| ^^^ InvalidReact: Cannot compile `fire`. All uses of foo must be either used with a fire() call in this effect or not used with a fire() call at all. foo was used with fire() on line 10:10 in this effect (11:11)
|
||||
12 | }
|
||||
13 |
|
||||
14 | nested();
|
||||
```
|
||||
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
function nested() {
|
||||
fire(foo(props));
|
||||
foo(props);
|
||||
}
|
||||
|
||||
nested();
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component({bar, baz}) {
|
||||
const foo = () => {
|
||||
console.log(bar, baz);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(bar), baz);
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
7 | };
|
||||
8 | useEffect(() => {
|
||||
> 9 | fire(foo(bar), baz);
|
||||
| ^^^^^^^^^^^^^^^^^^^ InvalidReact: Cannot compile `fire`. fire() can only take in a single call expression as an argument but received multiple arguments (9:9)
|
||||
10 | });
|
||||
11 |
|
||||
12 | return null;
|
||||
```
|
||||
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component({bar, baz}) {
|
||||
const foo = () => {
|
||||
console.log(bar, baz);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(bar), baz);
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enable
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
useEffect(() => {
|
||||
function nested() {
|
||||
fire(foo(props));
|
||||
}
|
||||
|
||||
nested();
|
||||
});
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
7 | };
|
||||
8 | useEffect(() => {
|
||||
> 9 | useEffect(() => {
|
||||
| ^^^^^^^^^ InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call useEffect within a function component (9:9)
|
||||
10 | function nested() {
|
||||
11 | fire(foo(props));
|
||||
12 | }
|
||||
```
|
||||
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// @enable
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
useEffect(() => {
|
||||
function nested() {
|
||||
fire(foo(props));
|
||||
}
|
||||
|
||||
nested();
|
||||
});
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = () => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(props);
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
7 | };
|
||||
8 | useEffect(() => {
|
||||
> 9 | fire(props);
|
||||
| ^^^^^^^^^^^ InvalidReact: Cannot compile `fire`. `fire()` can only receive a function call such as `fire(fn(a,b)). Method calls and other expressions are not allowed (9:9)
|
||||
10 | });
|
||||
11 |
|
||||
12 | return null;
|
||||
```
|
||||
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = () => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(props);
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire, useCallback} from 'react';
|
||||
|
||||
function Component({props, bar}) {
|
||||
const foo = () => {
|
||||
console.log(props);
|
||||
};
|
||||
fire(foo(props));
|
||||
|
||||
useCallback(() => {
|
||||
fire(foo(props));
|
||||
}, [foo, props]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
6 | console.log(props);
|
||||
7 | };
|
||||
> 8 | fire(foo(props));
|
||||
| ^^^^ Invariant: Cannot compile `fire`. Cannot use `fire` outside of a useEffect function (8:8)
|
||||
|
||||
Invariant: Cannot compile `fire`. Cannot use `fire` outside of a useEffect function (11:11)
|
||||
9 |
|
||||
10 | useCallback(() => {
|
||||
11 | fire(foo(props));
|
||||
```
|
||||
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// @enableFire
|
||||
import {fire, useCallback} from 'react';
|
||||
|
||||
function Component({props, bar}) {
|
||||
const foo = () => {
|
||||
console.log(props);
|
||||
};
|
||||
fire(foo(props));
|
||||
|
||||
useCallback(() => {
|
||||
fire(foo(props));
|
||||
}, [foo, props]);
|
||||
|
||||
return null;
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
|
||||
const deps = [foo, props];
|
||||
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
}, deps);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
11 | useEffect(() => {
|
||||
12 | fire(foo(props));
|
||||
> 13 | }, deps);
|
||||
| ^^^^ Invariant: Cannot compile `fire`. You must use an array literal for an effect dependency array when that effect uses `fire()` (13:13)
|
||||
14 |
|
||||
15 | return null;
|
||||
16 | }
|
||||
```
|
||||
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
|
||||
const deps = [foo, props];
|
||||
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
}, deps);
|
||||
|
||||
return null;
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
|
||||
const deps = [foo, props];
|
||||
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
}, ...deps);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
11 | useEffect(() => {
|
||||
12 | fire(foo(props));
|
||||
> 13 | }, ...deps);
|
||||
| ^^^^ Invariant: Cannot compile `fire`. You must use an array literal for an effect dependency array when that effect uses `fire()` (13:13)
|
||||
14 |
|
||||
15 | return null;
|
||||
16 | }
|
||||
```
|
||||
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
|
||||
const deps = [foo, props];
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
fire(foo(props));
|
||||
},
|
||||
...deps
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = () => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(...foo);
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
7 | };
|
||||
8 | useEffect(() => {
|
||||
> 9 | fire(...foo);
|
||||
| ^^^^^^^^^^^^ InvalidReact: Cannot compile `fire`. fire() can only take in a single call expression as an argument but received a spread argument (9:9)
|
||||
10 | });
|
||||
11 |
|
||||
12 | return null;
|
||||
```
|
||||
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = () => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(...foo);
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = () => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(props.foo());
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
7 | };
|
||||
8 | useEffect(() => {
|
||||
> 9 | fire(props.foo());
|
||||
| ^^^^^^^^^^^^^^^^^ InvalidReact: Cannot compile `fire`. `fire()` can only receive a function call such as `fire(fn(a,b)). Method calls and other expressions are not allowed (9:9)
|
||||
10 | });
|
||||
11 |
|
||||
12 | return null;
|
||||
```
|
||||
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = () => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(props.foo());
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire @inferEffectDependencies
|
||||
import {fire, useEffect} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = arg => {
|
||||
console.log(arg, props.bar);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { useFire } from "react/compiler-runtime";
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableFire @inferEffectDependencies
|
||||
import { fire, useEffect } from "react";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(5);
|
||||
let t0;
|
||||
if ($[0] !== props.bar) {
|
||||
t0 = (arg) => {
|
||||
console.log(arg, props.bar);
|
||||
};
|
||||
$[0] = props.bar;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const foo = t0;
|
||||
const t1 = useFire(foo);
|
||||
let t2;
|
||||
if ($[2] !== props || $[3] !== t1) {
|
||||
t2 = () => {
|
||||
t1(props);
|
||||
};
|
||||
$[2] = props;
|
||||
$[3] = t1;
|
||||
$[4] = t2;
|
||||
} else {
|
||||
t2 = $[4];
|
||||
}
|
||||
useEffect(t2, [t1, props]);
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Fixture not implemented
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// @enableFire @inferEffectDependencies
|
||||
import {fire, useEffect} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = arg => {
|
||||
console.log(arg, props.bar);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
function nested() {
|
||||
fire(foo(props));
|
||||
function innerNested() {
|
||||
fire(foo(props));
|
||||
}
|
||||
}
|
||||
|
||||
nested();
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { useFire } from "react/compiler-runtime";
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableFire
|
||||
import { fire } from "react";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(3);
|
||||
const foo = _temp;
|
||||
const t0 = useFire(foo);
|
||||
let t1;
|
||||
if ($[0] !== props || $[1] !== t0) {
|
||||
t1 = () => {
|
||||
t0(props);
|
||||
const nested = function nested() {
|
||||
t0(props);
|
||||
};
|
||||
|
||||
nested();
|
||||
};
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
$[2] = t1;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
}
|
||||
useEffect(t1);
|
||||
return null;
|
||||
}
|
||||
function _temp(props_0) {
|
||||
console.log(props_0);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Fixture not implemented
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
function nested() {
|
||||
fire(foo(props));
|
||||
function innerNested() {
|
||||
fire(foo(props));
|
||||
}
|
||||
}
|
||||
|
||||
nested();
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = () => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
fire(foo(props));
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { useFire } from "react/compiler-runtime";
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableFire
|
||||
import { fire } from "react";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(5);
|
||||
let t0;
|
||||
if ($[0] !== props) {
|
||||
t0 = () => {
|
||||
console.log(props);
|
||||
};
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const foo = t0;
|
||||
const t1 = useFire(foo);
|
||||
let t2;
|
||||
if ($[2] !== props || $[3] !== t1) {
|
||||
t2 = () => {
|
||||
t1(props);
|
||||
t1(props);
|
||||
};
|
||||
$[2] = props;
|
||||
$[3] = t1;
|
||||
$[4] = t2;
|
||||
} else {
|
||||
t2 = $[4];
|
||||
}
|
||||
useEffect(t2);
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Fixture not implemented
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = () => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
fire(foo(props));
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
}, [foo, props]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { useFire } from "react/compiler-runtime";
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableFire
|
||||
import { fire } from "react";
|
||||
|
||||
function Component(props) {
|
||||
const $ = _c(4);
|
||||
const foo = _temp;
|
||||
const t0 = useFire(foo);
|
||||
let t1;
|
||||
let t2;
|
||||
if ($[0] !== props || $[1] !== t0) {
|
||||
t1 = () => {
|
||||
t0(props);
|
||||
};
|
||||
t2 = [t0, props];
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
$[2] = t1;
|
||||
$[3] = t2;
|
||||
} else {
|
||||
t1 = $[2];
|
||||
t2 = $[3];
|
||||
}
|
||||
useEffect(t1, t2);
|
||||
return null;
|
||||
}
|
||||
function _temp(props_0) {
|
||||
console.log(props_0);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Fixture not implemented
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
const foo = props => {
|
||||
console.log(props);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(props));
|
||||
}, [foo, props]);
|
||||
|
||||
return null;
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component({bar, baz}) {
|
||||
const foo = () => {
|
||||
console.log(bar);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(bar));
|
||||
fire(baz(bar));
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
fire(foo(bar));
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { useFire } from "react/compiler-runtime";
|
||||
import { c as _c } from "react/compiler-runtime"; // @enableFire
|
||||
import { fire } from "react";
|
||||
|
||||
function Component(t0) {
|
||||
const $ = _c(9);
|
||||
const { bar, baz } = t0;
|
||||
let t1;
|
||||
if ($[0] !== bar) {
|
||||
t1 = () => {
|
||||
console.log(bar);
|
||||
};
|
||||
$[0] = bar;
|
||||
$[1] = t1;
|
||||
} else {
|
||||
t1 = $[1];
|
||||
}
|
||||
const foo = t1;
|
||||
const t2 = useFire(foo);
|
||||
const t3 = useFire(baz);
|
||||
let t4;
|
||||
if ($[2] !== bar || $[3] !== t2 || $[4] !== t3) {
|
||||
t4 = () => {
|
||||
t2(bar);
|
||||
t3(bar);
|
||||
};
|
||||
$[2] = bar;
|
||||
$[3] = t2;
|
||||
$[4] = t3;
|
||||
$[5] = t4;
|
||||
} else {
|
||||
t4 = $[5];
|
||||
}
|
||||
useEffect(t4);
|
||||
let t5;
|
||||
if ($[6] !== bar || $[7] !== t2) {
|
||||
t5 = () => {
|
||||
t2(bar);
|
||||
};
|
||||
$[6] = bar;
|
||||
$[7] = t2;
|
||||
$[8] = t5;
|
||||
} else {
|
||||
t5 = $[8];
|
||||
}
|
||||
useEffect(t5);
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Fixture not implemented
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component({bar, baz}) {
|
||||
const foo = () => {
|
||||
console.log(bar);
|
||||
};
|
||||
useEffect(() => {
|
||||
fire(foo(bar));
|
||||
fire(baz(bar));
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
fire(foo(bar));
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
useEffect();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @enableFire
|
||||
import { fire } from "react";
|
||||
|
||||
function Component(props) {
|
||||
useEffect();
|
||||
return null;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Fixture not implemented
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// @enableFire
|
||||
import {fire} from 'react';
|
||||
|
||||
function Component(props) {
|
||||
useEffect();
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -29,6 +29,7 @@ const DEV_ROLLUP_CONFIG = {
|
||||
file: 'dist/index.js',
|
||||
format: 'cjs',
|
||||
sourcemap: false,
|
||||
inlineDynamicImports: true,
|
||||
},
|
||||
treeshake: {
|
||||
moduleSideEffects: false,
|
||||
|
||||
@@ -33,6 +33,7 @@ const DEV_ROLLUP_CONFIG = {
|
||||
format: 'cjs',
|
||||
sourcemap: false,
|
||||
exports: 'named',
|
||||
inlineDynamicImports: true,
|
||||
},
|
||||
plugins: [
|
||||
typescript({
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"src"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
"react": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^0.0.0-experimental"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rimraf dist && rollup --config --bundleConfigAsCjs",
|
||||
|
||||
@@ -21,6 +21,7 @@ const PROD_ROLLUP_CONFIG = {
|
||||
file: 'dist/index.js',
|
||||
format: 'cjs',
|
||||
sourcemap: true,
|
||||
inlineDynamicImports: true,
|
||||
},
|
||||
plugins: [
|
||||
typescript({
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
**/node_modules
|
||||
client
|
||||
server
|
||||
@@ -0,0 +1 @@
|
||||
ignore-engines true
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"private": "true",
|
||||
"name": "react-forgive-client",
|
||||
"version": "0.0.0",
|
||||
"description": "Experimental LSP client",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "echo 'no build'",
|
||||
"test": "echo 'no tests'"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/facebook/react.git",
|
||||
"directory": "compiler/packages/react-forgive"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-languageclient": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/vscode": "^1.95.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
import * as path from 'path';
|
||||
import {ExtensionContext, window as Window} from 'vscode';
|
||||
|
||||
import {
|
||||
LanguageClient,
|
||||
LanguageClientOptions,
|
||||
ServerOptions,
|
||||
TransportKind,
|
||||
} from 'vscode-languageclient/node';
|
||||
|
||||
let client: LanguageClient;
|
||||
|
||||
export function activate(context: ExtensionContext) {
|
||||
const serverModule = context.asAbsolutePath(path.join('dist', 'server.js'));
|
||||
|
||||
// If the extension is launched in debug mode then the debug server options are used
|
||||
// Otherwise the run options are used
|
||||
const serverOptions: ServerOptions = {
|
||||
run: {
|
||||
module: serverModule,
|
||||
transport: TransportKind.ipc,
|
||||
options: {cwd: process.cwd()},
|
||||
},
|
||||
debug: {
|
||||
module: serverModule,
|
||||
transport: TransportKind.ipc,
|
||||
options: {cwd: process.cwd()},
|
||||
},
|
||||
};
|
||||
|
||||
const clientOptions: LanguageClientOptions = {
|
||||
documentSelector: [
|
||||
{scheme: 'file', language: 'javascriptreact'},
|
||||
{scheme: 'file', language: 'typescriptreact'},
|
||||
],
|
||||
progressOnInitialization: true,
|
||||
};
|
||||
|
||||
// Create the language client and start the client.
|
||||
try {
|
||||
client = new LanguageClient(
|
||||
'react-forgive',
|
||||
'React Analyzer',
|
||||
serverOptions,
|
||||
clientOptions,
|
||||
);
|
||||
} catch {
|
||||
Window.showErrorMessage(
|
||||
`React Analyzer couldn't be started. See the output channel for details.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
client.registerProposedFeatures();
|
||||
client.start();
|
||||
}
|
||||
|
||||
export function deactivate(): Thenable<void> | undefined {
|
||||
if (client !== undefined) {
|
||||
return client.stop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@types/vscode@^1.95.0":
|
||||
version "1.96.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/vscode/-/vscode-1.96.0.tgz#3181004bf25d71677ae4aacdd7605a3fd7edf08e"
|
||||
integrity sha512-qvZbSZo+K4ZYmmDuaodMbAa67Pl6VDQzLKFka6rq+3WUTY4Kro7Bwoi0CuZLO/wema0ygcmpwow7zZfPJTs5jg==
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
|
||||
brace-expansion@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
|
||||
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
|
||||
minimatch@^5.1.0:
|
||||
version "5.1.6"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
|
||||
integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
semver@^7.3.7:
|
||||
version "7.6.3"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
|
||||
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
|
||||
|
||||
vscode-jsonrpc@8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9"
|
||||
integrity sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==
|
||||
|
||||
vscode-languageclient@^9.0.1:
|
||||
version "9.0.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz#cdfe20267726c8d4db839dc1e9d1816e1296e854"
|
||||
integrity sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==
|
||||
dependencies:
|
||||
minimatch "^5.1.0"
|
||||
semver "^7.3.7"
|
||||
vscode-languageserver-protocol "3.17.5"
|
||||
|
||||
vscode-languageserver-protocol@3.17.5:
|
||||
version "3.17.5"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz#864a8b8f390835572f4e13bd9f8313d0e3ac4bea"
|
||||
integrity sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==
|
||||
dependencies:
|
||||
vscode-jsonrpc "8.2.0"
|
||||
vscode-languageserver-types "3.17.5"
|
||||
|
||||
vscode-languageserver-types@3.17.5:
|
||||
version "3.17.5"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a"
|
||||
integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "react-forgive",
|
||||
"displayName": "React Analyzer",
|
||||
"description": "React LSP",
|
||||
"license": "MIT",
|
||||
"version": "0.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/facebook/react.git",
|
||||
"directory": "compiler/packages/react-forgive"
|
||||
},
|
||||
"categories": [
|
||||
"Programming Languages"
|
||||
],
|
||||
"keywords": [
|
||||
"react",
|
||||
"react analyzer",
|
||||
"react compiler"
|
||||
],
|
||||
"publisher": "Meta",
|
||||
"engines": {
|
||||
"vscode": "^1.75.0"
|
||||
},
|
||||
"activationEvents": [
|
||||
"onLanguage:javascriptreact",
|
||||
"onLanguage:typescriptreact"
|
||||
],
|
||||
"main": "./dist/extension.js",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "react-forgive.toggleAll",
|
||||
"title": "React Analyzer: Toggle on/off"
|
||||
}
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"compile": "rimraf dist && concurrently -n server,client \"yarn run esbuild:server --sourcemap\" \"yarn run esbuild:client --sourcemap\"",
|
||||
"dev": "yarn run package && yarn run install-ext",
|
||||
"esbuild:client": "esbuild ./client/src/extension.ts --bundle --outfile=dist/extension.js --external:vscode --format=cjs --platform=node",
|
||||
"esbuild:server": "esbuild ./server/src/index.ts --bundle --outfile=dist/server.js --external:vscode --format=cjs --platform=node",
|
||||
"install-ext": "code --install-extension react-forgive-0.0.0.vsix",
|
||||
"lint": "eslint src --ext ts",
|
||||
"package": "rm -f react-forgive-0.0.0.vsix && vsce package --yarn",
|
||||
"postinstall": "cd client && yarn install && cd ../server && yarn install && cd ..",
|
||||
"pretest": "yarn run compile && yarn run lint",
|
||||
"test": "vscode-test",
|
||||
"vscode:prepublish": "yarn run compile",
|
||||
"watch": "concurrently --kill-others -n server,client \"run esbuild:server --sourcemap --watch\" \"run esbuild:client --sourcemap --watch\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.13.0",
|
||||
"@types/node": "^20",
|
||||
"esbuild": "^0.24.0",
|
||||
"eslint": "^9.13.0",
|
||||
"typescript-eslint": "^8.16.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"private": "true",
|
||||
"name": "react-forgive-server",
|
||||
"version": "0.0.0",
|
||||
"description": "Experimental LSP server",
|
||||
"license": "MIT",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "rimraf dist && rollup --config --bundleConfigAsCjs",
|
||||
"test": "echo 'no tests'"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/facebook/react.git",
|
||||
"directory": "compiler/packages/react-forgive"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.26.0",
|
||||
"@babel/parser": "^7.26.0",
|
||||
"@babel/plugin-syntax-typescript": "^7.25.9",
|
||||
"@babel/types": "^7.26.0",
|
||||
"cosmiconfig": "^9.0.0",
|
||||
"prettier": "^3.3.3",
|
||||
"vscode-languageserver": "^9.0.1",
|
||||
"vscode-languageserver-textdocument": "^1.0.12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import type * as BabelCore from '@babel/core';
|
||||
import {parseAsync, transformFromAstAsync} from '@babel/core';
|
||||
import BabelPluginReactCompiler, {
|
||||
type PluginOptions,
|
||||
} from 'babel-plugin-react-compiler/src';
|
||||
import * as babelParser from 'prettier/plugins/babel.js';
|
||||
import estreeParser from 'prettier/plugins/estree';
|
||||
import * as typescriptParser from 'prettier/plugins/typescript';
|
||||
import * as prettier from 'prettier/standalone';
|
||||
|
||||
type CompileOptions = {
|
||||
text: string;
|
||||
file: string;
|
||||
options: PluginOptions | null;
|
||||
};
|
||||
export async function compile({
|
||||
text,
|
||||
file,
|
||||
options,
|
||||
}: CompileOptions): Promise<BabelCore.BabelFileResult> {
|
||||
const ast = await parseAsync(text, {
|
||||
sourceFileName: file,
|
||||
parserOpts: {
|
||||
plugins: ['typescript', 'jsx'],
|
||||
},
|
||||
sourceType: 'module',
|
||||
});
|
||||
const plugins =
|
||||
options != null
|
||||
? [[BabelPluginReactCompiler, options]]
|
||||
: [[BabelPluginReactCompiler]];
|
||||
const result = await transformFromAstAsync(ast, text, {
|
||||
filename: file,
|
||||
highlightCode: false,
|
||||
retainLines: true,
|
||||
plugins,
|
||||
sourceType: 'module',
|
||||
sourceFileName: file,
|
||||
});
|
||||
if (result?.code == null) {
|
||||
throw new Error(
|
||||
`Expected BabelPluginReactCompiler to compile successfully, got ${result}`,
|
||||
);
|
||||
}
|
||||
result.code = await prettier.format(result.code, {
|
||||
semi: false,
|
||||
parser: 'babel-ts',
|
||||
plugins: [babelParser, estreeParser, typescriptParser],
|
||||
});
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {
|
||||
parsePluginOptions,
|
||||
type PluginOptions,
|
||||
} from 'babel-plugin-react-compiler/src';
|
||||
import {cosmiconfigSync} from 'cosmiconfig';
|
||||
|
||||
export function resolveReactConfig(projectPath: string): PluginOptions | null {
|
||||
const explorerSync = cosmiconfigSync('react', {
|
||||
searchStrategy: 'project',
|
||||
cache: true,
|
||||
});
|
||||
const result = explorerSync.search(projectPath);
|
||||
if (result != null) {
|
||||
return parsePluginOptions(result.config);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {TextDocument} from 'vscode-languageserver-textdocument';
|
||||
import {
|
||||
createConnection,
|
||||
type InitializeParams,
|
||||
type InitializeResult,
|
||||
ProposedFeatures,
|
||||
TextDocuments,
|
||||
TextDocumentSyncKind,
|
||||
} from 'vscode-languageserver/node';
|
||||
import {compile} from './compiler';
|
||||
import {type PluginOptions} from 'babel-plugin-react-compiler/src';
|
||||
import {resolveReactConfig} from './compiler/options';
|
||||
|
||||
const SUPPORTED_LANGUAGE_IDS = new Set([
|
||||
'javascript',
|
||||
'javascriptreact',
|
||||
'typescript',
|
||||
'typescriptreact',
|
||||
]);
|
||||
|
||||
const connection = createConnection(ProposedFeatures.all);
|
||||
connection.console.info(`React Analyzer running in node ${process.version}`);
|
||||
|
||||
const compiledCache = new WeakMap<TextDocument, string>();
|
||||
|
||||
const documents = new TextDocuments(TextDocument);
|
||||
documents.listen(connection);
|
||||
|
||||
let compilerOptions: PluginOptions | null = null;
|
||||
|
||||
connection.onInitialize((_params: InitializeParams) => {
|
||||
// TODO(@poteto) get config fr
|
||||
compilerOptions = resolveReactConfig('.');
|
||||
const result: InitializeResult = {
|
||||
capabilities: {
|
||||
textDocumentSync: TextDocumentSyncKind.Full,
|
||||
codeLensProvider: {resolveProvider: true},
|
||||
},
|
||||
};
|
||||
return result;
|
||||
});
|
||||
|
||||
connection.onInitialized(() => {
|
||||
connection.console.log('initialized');
|
||||
});
|
||||
|
||||
documents.onDidOpen(async event => {
|
||||
if (SUPPORTED_LANGUAGE_IDS.has(event.document.languageId)) {
|
||||
const result = await compile({
|
||||
text: event.document.getText(),
|
||||
file: event.document.uri,
|
||||
options: compilerOptions,
|
||||
});
|
||||
if (result.code != null) {
|
||||
compiledCache.set(event.document, result.code);
|
||||
connection.console.log(result.code);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
documents.onDidChangeContent(async event => {
|
||||
if (SUPPORTED_LANGUAGE_IDS.has(event.document.languageId)) {
|
||||
const result = await compile({
|
||||
text: event.document.getText(),
|
||||
file: event.document.uri,
|
||||
options: compilerOptions,
|
||||
});
|
||||
if (result.code != null) {
|
||||
compiledCache.set(event.document, result.code);
|
||||
connection.console.log(result.code);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connection.onDidChangeWatchedFiles(change => {
|
||||
connection.console.log(
|
||||
change.changes.map(c => `File changed: ${c.uri}`).join('\n'),
|
||||
);
|
||||
});
|
||||
|
||||
connection.onCodeLens(params => {
|
||||
connection.console.log(JSON.stringify(params, null, 2));
|
||||
return [];
|
||||
});
|
||||
|
||||
connection.listen();
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "@tsconfig/strictest/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "ES2015",
|
||||
"moduleResolution": "Bundler",
|
||||
"rootDir": "../../..",
|
||||
"noEmit": true,
|
||||
"jsx": "react-jsxdev",
|
||||
"target": "ES2015",
|
||||
"sourceMap": false,
|
||||
"removeComments": true,
|
||||
|
||||
"strictNullChecks": false
|
||||
},
|
||||
"exclude": ["node_modules", ".vscode-test"],
|
||||
"include": ["src/**/*.ts"]
|
||||
}
|
||||
@@ -0,0 +1,410 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@ampproject/remapping@^2.2.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4"
|
||||
integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==
|
||||
dependencies:
|
||||
"@jridgewell/gen-mapping" "^0.3.5"
|
||||
"@jridgewell/trace-mapping" "^0.3.24"
|
||||
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0", "@babel/code-frame@^7.26.2":
|
||||
version "7.26.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85"
|
||||
integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.25.9"
|
||||
js-tokens "^4.0.0"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
"@babel/compat-data@^7.25.9":
|
||||
version "7.26.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.3.tgz#99488264a56b2aded63983abd6a417f03b92ed02"
|
||||
integrity sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==
|
||||
|
||||
"@babel/core@^7.26.0":
|
||||
version "7.26.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40"
|
||||
integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==
|
||||
dependencies:
|
||||
"@ampproject/remapping" "^2.2.0"
|
||||
"@babel/code-frame" "^7.26.0"
|
||||
"@babel/generator" "^7.26.0"
|
||||
"@babel/helper-compilation-targets" "^7.25.9"
|
||||
"@babel/helper-module-transforms" "^7.26.0"
|
||||
"@babel/helpers" "^7.26.0"
|
||||
"@babel/parser" "^7.26.0"
|
||||
"@babel/template" "^7.25.9"
|
||||
"@babel/traverse" "^7.25.9"
|
||||
"@babel/types" "^7.26.0"
|
||||
convert-source-map "^2.0.0"
|
||||
debug "^4.1.0"
|
||||
gensync "^1.0.0-beta.2"
|
||||
json5 "^2.2.3"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/generator@^7.26.0", "@babel/generator@^7.26.3":
|
||||
version "7.26.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.3.tgz#ab8d4360544a425c90c248df7059881f4b2ce019"
|
||||
integrity sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==
|
||||
dependencies:
|
||||
"@babel/parser" "^7.26.3"
|
||||
"@babel/types" "^7.26.3"
|
||||
"@jridgewell/gen-mapping" "^0.3.5"
|
||||
"@jridgewell/trace-mapping" "^0.3.25"
|
||||
jsesc "^3.0.2"
|
||||
|
||||
"@babel/helper-compilation-targets@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz#55af025ce365be3cdc0c1c1e56c6af617ce88875"
|
||||
integrity sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==
|
||||
dependencies:
|
||||
"@babel/compat-data" "^7.25.9"
|
||||
"@babel/helper-validator-option" "^7.25.9"
|
||||
browserslist "^4.24.0"
|
||||
lru-cache "^5.1.1"
|
||||
semver "^6.3.1"
|
||||
|
||||
"@babel/helper-module-imports@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715"
|
||||
integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==
|
||||
dependencies:
|
||||
"@babel/traverse" "^7.25.9"
|
||||
"@babel/types" "^7.25.9"
|
||||
|
||||
"@babel/helper-module-transforms@^7.26.0":
|
||||
version "7.26.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae"
|
||||
integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==
|
||||
dependencies:
|
||||
"@babel/helper-module-imports" "^7.25.9"
|
||||
"@babel/helper-validator-identifier" "^7.25.9"
|
||||
"@babel/traverse" "^7.25.9"
|
||||
|
||||
"@babel/helper-plugin-utils@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz#9cbdd63a9443a2c92a725cca7ebca12cc8dd9f46"
|
||||
integrity sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==
|
||||
|
||||
"@babel/helper-string-parser@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c"
|
||||
integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7"
|
||||
integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==
|
||||
|
||||
"@babel/helper-validator-option@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72"
|
||||
integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==
|
||||
|
||||
"@babel/helpers@^7.26.0":
|
||||
version "7.26.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.0.tgz#30e621f1eba5aa45fe6f4868d2e9154d884119a4"
|
||||
integrity sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==
|
||||
dependencies:
|
||||
"@babel/template" "^7.25.9"
|
||||
"@babel/types" "^7.26.0"
|
||||
|
||||
"@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.3":
|
||||
version "7.26.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.3.tgz#8c51c5db6ddf08134af1ddbacf16aaab48bac234"
|
||||
integrity sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==
|
||||
dependencies:
|
||||
"@babel/types" "^7.26.3"
|
||||
|
||||
"@babel/plugin-syntax-typescript@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399"
|
||||
integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.25.9"
|
||||
|
||||
"@babel/template@^7.25.9":
|
||||
version "7.25.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016"
|
||||
integrity sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.25.9"
|
||||
"@babel/parser" "^7.25.9"
|
||||
"@babel/types" "^7.25.9"
|
||||
|
||||
"@babel/traverse@^7.25.9":
|
||||
version "7.26.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.4.tgz#ac3a2a84b908dde6d463c3bfa2c5fdc1653574bd"
|
||||
integrity sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.26.2"
|
||||
"@babel/generator" "^7.26.3"
|
||||
"@babel/parser" "^7.26.3"
|
||||
"@babel/template" "^7.25.9"
|
||||
"@babel/types" "^7.26.3"
|
||||
debug "^4.3.1"
|
||||
globals "^11.1.0"
|
||||
|
||||
"@babel/types@^7.25.9", "@babel/types@^7.26.0", "@babel/types@^7.26.3":
|
||||
version "7.26.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.3.tgz#37e79830f04c2b5687acc77db97fbc75fb81f3c0"
|
||||
integrity sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.25.9"
|
||||
"@babel/helper-validator-identifier" "^7.25.9"
|
||||
|
||||
"@jridgewell/gen-mapping@^0.3.5":
|
||||
version "0.3.8"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142"
|
||||
integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==
|
||||
dependencies:
|
||||
"@jridgewell/set-array" "^1.2.1"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
"@jridgewell/trace-mapping" "^0.3.24"
|
||||
|
||||
"@jridgewell/resolve-uri@^3.1.0":
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
|
||||
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
|
||||
|
||||
"@jridgewell/set-array@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280"
|
||||
integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
|
||||
|
||||
"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
|
||||
integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
|
||||
|
||||
"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25":
|
||||
version "0.3.25"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
|
||||
integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
|
||||
dependencies:
|
||||
"@jridgewell/resolve-uri" "^3.1.0"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||
|
||||
argparse@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||
|
||||
browserslist@^4.24.0:
|
||||
version "4.24.3"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.3.tgz#5fc2725ca8fb3c1432e13dac278c7cc103e026d2"
|
||||
integrity sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30001688"
|
||||
electron-to-chromium "^1.5.73"
|
||||
node-releases "^2.0.19"
|
||||
update-browserslist-db "^1.1.1"
|
||||
|
||||
callsites@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
||||
|
||||
caniuse-lite@^1.0.30001688:
|
||||
version "1.0.30001690"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz#f2d15e3aaf8e18f76b2b8c1481abde063b8104c8"
|
||||
integrity sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==
|
||||
|
||||
convert-source-map@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
|
||||
integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
|
||||
|
||||
cosmiconfig@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d"
|
||||
integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==
|
||||
dependencies:
|
||||
env-paths "^2.2.1"
|
||||
import-fresh "^3.3.0"
|
||||
js-yaml "^4.1.0"
|
||||
parse-json "^5.2.0"
|
||||
|
||||
debug@^4.1.0, debug@^4.3.1:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a"
|
||||
integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
|
||||
dependencies:
|
||||
ms "^2.1.3"
|
||||
|
||||
electron-to-chromium@^1.5.73:
|
||||
version "1.5.74"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.74.tgz#cb886b504a6467e4c00bea3317edb38393c53413"
|
||||
integrity sha512-ck3//9RC+6oss/1Bh9tiAVFy5vfSKbRHAFh7Z3/eTRkEqJeWgymloShB17Vg3Z4nmDNp35vAd1BZ6CMW4Wt6Iw==
|
||||
|
||||
env-paths@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
|
||||
integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
|
||||
|
||||
error-ex@^1.3.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
||||
integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
|
||||
dependencies:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
escalade@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
|
||||
integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
|
||||
|
||||
gensync@^1.0.0-beta.2:
|
||||
version "1.0.0-beta.2"
|
||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
|
||||
|
||||
globals@^11.1.0:
|
||||
version "11.12.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
||||
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
|
||||
|
||||
import-fresh@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
|
||||
integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
|
||||
dependencies:
|
||||
parent-module "^1.0.0"
|
||||
resolve-from "^4.0.0"
|
||||
|
||||
is-arrayish@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
|
||||
|
||||
js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
jsesc@^3.0.2:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d"
|
||||
integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==
|
||||
|
||||
json-parse-even-better-errors@^2.3.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
||||
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
|
||||
|
||||
json5@^2.2.3:
|
||||
version "2.2.3"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
|
||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||
|
||||
lines-and-columns@^1.1.6:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||
|
||||
lru-cache@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
|
||||
integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
|
||||
dependencies:
|
||||
yallist "^3.0.2"
|
||||
|
||||
ms@^2.1.3:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
node-releases@^2.0.19:
|
||||
version "2.0.19"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314"
|
||||
integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==
|
||||
|
||||
parent-module@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
|
||||
integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
|
||||
dependencies:
|
||||
callsites "^3.0.0"
|
||||
|
||||
parse-json@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
|
||||
integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
error-ex "^1.3.1"
|
||||
json-parse-even-better-errors "^2.3.0"
|
||||
lines-and-columns "^1.1.6"
|
||||
|
||||
picocolors@^1.0.0, picocolors@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
|
||||
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
|
||||
|
||||
prettier@^3.3.3:
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.4.2.tgz#a5ce1fb522a588bf2b78ca44c6e6fe5aa5a2b13f"
|
||||
integrity sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==
|
||||
|
||||
resolve-from@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
||||
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
||||
|
||||
semver@^6.3.1:
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||
|
||||
update-browserslist-db@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5"
|
||||
integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==
|
||||
dependencies:
|
||||
escalade "^3.2.0"
|
||||
picocolors "^1.1.0"
|
||||
|
||||
vscode-jsonrpc@8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9"
|
||||
integrity sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==
|
||||
|
||||
vscode-languageserver-protocol@3.17.5:
|
||||
version "3.17.5"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz#864a8b8f390835572f4e13bd9f8313d0e3ac4bea"
|
||||
integrity sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==
|
||||
dependencies:
|
||||
vscode-jsonrpc "8.2.0"
|
||||
vscode-languageserver-types "3.17.5"
|
||||
|
||||
vscode-languageserver-textdocument@^1.0.12:
|
||||
version "1.0.12"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz#457ee04271ab38998a093c68c2342f53f6e4a631"
|
||||
integrity sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==
|
||||
|
||||
vscode-languageserver-types@3.17.5:
|
||||
version "3.17.5"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a"
|
||||
integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==
|
||||
|
||||
vscode-languageserver@^9.0.1:
|
||||
version "9.0.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz#500aef82097eb94df90d008678b0b6b5f474015b"
|
||||
integrity sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==
|
||||
dependencies:
|
||||
vscode-languageserver-protocol "3.17.5"
|
||||
|
||||
yallist@^3.0.2:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
||||
+501
-46
@@ -1700,6 +1700,126 @@
|
||||
dependencies:
|
||||
"@jridgewell/trace-mapping" "0.3.9"
|
||||
|
||||
"@esbuild/aix-ppc64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz#b57697945b50e99007b4c2521507dc613d4a648c"
|
||||
integrity sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==
|
||||
|
||||
"@esbuild/android-arm64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz#1add7e0af67acefd556e407f8497e81fddad79c0"
|
||||
integrity sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==
|
||||
|
||||
"@esbuild/android-arm@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.0.tgz#ab7263045fa8e090833a8e3c393b60d59a789810"
|
||||
integrity sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==
|
||||
|
||||
"@esbuild/android-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.0.tgz#e8f8b196cfdfdd5aeaebbdb0110983460440e705"
|
||||
integrity sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==
|
||||
|
||||
"@esbuild/darwin-arm64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz#2d0d9414f2acbffd2d86e98253914fca603a53dd"
|
||||
integrity sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==
|
||||
|
||||
"@esbuild/darwin-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz#33087aab31a1eb64c89daf3d2cf8ce1775656107"
|
||||
integrity sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz#bb76e5ea9e97fa3c753472f19421075d3a33e8a7"
|
||||
integrity sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==
|
||||
|
||||
"@esbuild/freebsd-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz#e0e2ce9249fdf6ee29e5dc3d420c7007fa579b93"
|
||||
integrity sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==
|
||||
|
||||
"@esbuild/linux-arm64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz#d1b2aa58085f73ecf45533c07c82d81235388e75"
|
||||
integrity sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==
|
||||
|
||||
"@esbuild/linux-arm@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz#8e4915df8ea3e12b690a057e77a47b1d5935ef6d"
|
||||
integrity sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==
|
||||
|
||||
"@esbuild/linux-ia32@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz#8200b1110666c39ab316572324b7af63d82013fb"
|
||||
integrity sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==
|
||||
|
||||
"@esbuild/linux-loong64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz#6ff0c99cf647504df321d0640f0d32e557da745c"
|
||||
integrity sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==
|
||||
|
||||
"@esbuild/linux-mips64el@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz#3f720ccd4d59bfeb4c2ce276a46b77ad380fa1f3"
|
||||
integrity sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==
|
||||
|
||||
"@esbuild/linux-ppc64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz#9d6b188b15c25afd2e213474bf5f31e42e3aa09e"
|
||||
integrity sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==
|
||||
|
||||
"@esbuild/linux-riscv64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz#f989fdc9752dfda286c9cd87c46248e4dfecbc25"
|
||||
integrity sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==
|
||||
|
||||
"@esbuild/linux-s390x@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz#29ebf87e4132ea659c1489fce63cd8509d1c7319"
|
||||
integrity sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==
|
||||
|
||||
"@esbuild/linux-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz#4af48c5c0479569b1f359ffbce22d15f261c0cef"
|
||||
integrity sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==
|
||||
|
||||
"@esbuild/netbsd-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz#1ae73d23cc044a0ebd4f198334416fb26c31366c"
|
||||
integrity sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==
|
||||
|
||||
"@esbuild/openbsd-arm64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz#5d904a4f5158c89859fd902c427f96d6a9e632e2"
|
||||
integrity sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==
|
||||
|
||||
"@esbuild/openbsd-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz#4c8aa88c49187c601bae2971e71c6dc5e0ad1cdf"
|
||||
integrity sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==
|
||||
|
||||
"@esbuild/sunos-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz#8ddc35a0ea38575fa44eda30a5ee01ae2fa54dd4"
|
||||
integrity sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==
|
||||
|
||||
"@esbuild/win32-arm64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz#6e79c8543f282c4539db684a207ae0e174a9007b"
|
||||
integrity sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==
|
||||
|
||||
"@esbuild/win32-ia32@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz#057af345da256b7192d18b676a02e95d0fa39103"
|
||||
integrity sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==
|
||||
|
||||
"@esbuild/win32-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz#168ab1c7e1c318b922637fad8f339d48b01e1244"
|
||||
integrity sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
|
||||
@@ -1712,11 +1832,32 @@
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.1.tgz#a547badfc719eb3e5f4b556325e542fbe9d7a18f"
|
||||
integrity sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==
|
||||
|
||||
"@eslint-community/regexpp@^4.12.1":
|
||||
version "4.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0"
|
||||
integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
|
||||
|
||||
"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1":
|
||||
version "4.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63"
|
||||
integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==
|
||||
|
||||
"@eslint/config-array@^0.19.0":
|
||||
version "0.19.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.1.tgz#734aaea2c40be22bbb1f2a9dac687c57a6a4c984"
|
||||
integrity sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==
|
||||
dependencies:
|
||||
"@eslint/object-schema" "^2.1.5"
|
||||
debug "^4.3.1"
|
||||
minimatch "^3.1.2"
|
||||
|
||||
"@eslint/core@^0.9.0":
|
||||
version "0.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.9.1.tgz#31763847308ef6b7084a4505573ac9402c51f9d1"
|
||||
integrity sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.15"
|
||||
|
||||
"@eslint/eslintrc@^2.1.4":
|
||||
version "2.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad"
|
||||
@@ -1732,6 +1873,21 @@
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/eslintrc@^3.2.0":
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c"
|
||||
integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==
|
||||
dependencies:
|
||||
ajv "^6.12.4"
|
||||
debug "^4.3.2"
|
||||
espree "^10.0.1"
|
||||
globals "^14.0.0"
|
||||
ignore "^5.2.0"
|
||||
import-fresh "^3.2.1"
|
||||
js-yaml "^4.1.0"
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/js@8.57.0":
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f"
|
||||
@@ -1742,6 +1898,23 @@
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2"
|
||||
integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==
|
||||
|
||||
"@eslint/js@9.17.0", "@eslint/js@^9.13.0":
|
||||
version "9.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.17.0.tgz#1523e586791f80376a6f8398a3964455ecc651ec"
|
||||
integrity sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==
|
||||
|
||||
"@eslint/object-schema@^2.1.5":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.5.tgz#8670a8f6258a2be5b2c620ff314a1d984c23eb2e"
|
||||
integrity sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==
|
||||
|
||||
"@eslint/plugin-kit@^0.2.3":
|
||||
version "0.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz#2b78e7bb3755784bb13faa8932a1d994d6537792"
|
||||
integrity sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==
|
||||
dependencies:
|
||||
levn "^0.4.1"
|
||||
|
||||
"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0":
|
||||
version "9.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
|
||||
@@ -1754,6 +1927,19 @@
|
||||
dependencies:
|
||||
"@hapi/hoek" "^9.0.0"
|
||||
|
||||
"@humanfs/core@^0.19.1":
|
||||
version "0.19.1"
|
||||
resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77"
|
||||
integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==
|
||||
|
||||
"@humanfs/node@^0.16.6":
|
||||
version "0.16.6"
|
||||
resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e"
|
||||
integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==
|
||||
dependencies:
|
||||
"@humanfs/core" "^0.19.1"
|
||||
"@humanwhocodes/retry" "^0.3.0"
|
||||
|
||||
"@humanwhocodes/config-array@^0.11.14":
|
||||
version "0.11.14"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b"
|
||||
@@ -1787,6 +1973,16 @@
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3"
|
||||
integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==
|
||||
|
||||
"@humanwhocodes/retry@^0.3.0":
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a"
|
||||
integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==
|
||||
|
||||
"@humanwhocodes/retry@^0.4.1":
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b"
|
||||
integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==
|
||||
|
||||
"@isaacs/cliui@^8.0.2":
|
||||
version "8.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
|
||||
@@ -2512,17 +2708,18 @@
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@rollup/plugin-commonjs@^25.0.7":
|
||||
version "25.0.7"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.7.tgz#145cec7589ad952171aeb6a585bbeabd0fd3b4cf"
|
||||
integrity sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==
|
||||
"@rollup/plugin-commonjs@^28.0.2":
|
||||
version "28.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.2.tgz#193d7a86470f112b56927c1d821ee45951a819ea"
|
||||
integrity sha512-BEFI2EDqzl+vA1rl97IDRZ61AIwGH093d9nz8+dThxJNH8oSoB7MjWvPCX3dkaK1/RCJ/1v/R1XB15FuSs0fQw==
|
||||
dependencies:
|
||||
"@rollup/pluginutils" "^5.0.1"
|
||||
commondir "^1.0.1"
|
||||
estree-walker "^2.0.2"
|
||||
glob "^8.0.3"
|
||||
fdir "^6.2.0"
|
||||
is-reference "1.2.1"
|
||||
magic-string "^0.30.3"
|
||||
picomatch "^4.0.2"
|
||||
|
||||
"@rollup/plugin-json@^6.1.0":
|
||||
version "6.1.0"
|
||||
@@ -2531,15 +2728,14 @@
|
||||
dependencies:
|
||||
"@rollup/pluginutils" "^5.1.0"
|
||||
|
||||
"@rollup/plugin-node-resolve@^15.2.3":
|
||||
version "15.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz#e5e0b059bd85ca57489492f295ce88c2d4b0daf9"
|
||||
integrity sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==
|
||||
"@rollup/plugin-node-resolve@^16.0.0":
|
||||
version "16.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.0.tgz#b1a0594661f40d7b061d82136e847354ff85f211"
|
||||
integrity sha512-0FPvAeVUT/zdWoO0jnb/V5BlBsUSNfkIOtFHzMO4H9MOklrmQFY6FduVHKucNb/aTFxvnGhj4MNj/T1oNdDfNg==
|
||||
dependencies:
|
||||
"@rollup/pluginutils" "^5.0.1"
|
||||
"@types/resolve" "1.20.2"
|
||||
deepmerge "^4.2.2"
|
||||
is-builtin-module "^3.2.1"
|
||||
is-module "^1.0.0"
|
||||
resolve "^1.22.1"
|
||||
|
||||
@@ -2552,10 +2748,10 @@
|
||||
smob "^1.0.0"
|
||||
terser "^5.17.4"
|
||||
|
||||
"@rollup/plugin-typescript@^11.1.6":
|
||||
version "11.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-11.1.6.tgz#724237d5ec12609ec01429f619d2a3e7d4d1b22b"
|
||||
integrity sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==
|
||||
"@rollup/plugin-typescript@^12.1.2":
|
||||
version "12.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-12.1.2.tgz#ebaeec2e7376faa889030ccd7cb485a649e63118"
|
||||
integrity sha512-cdtSp154H5sv637uMr1a8OTWB0L1SWDSm1rDGiyfcGcvQ6cuTs4MDk2BVEBGysUWago4OJN4EQZqOTl/QY3Jgg==
|
||||
dependencies:
|
||||
"@rollup/pluginutils" "^5.1.0"
|
||||
resolve "^1.22.1"
|
||||
@@ -2827,6 +3023,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
|
||||
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
|
||||
|
||||
"@types/estree@^1.0.6":
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
|
||||
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
|
||||
|
||||
"@types/fbt@^1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/fbt/-/fbt-1.0.4.tgz#0d9e427f91fcff46bdcf2ca42a63343096565451"
|
||||
@@ -2906,7 +3107,7 @@
|
||||
"@types/tough-cookie" "*"
|
||||
parse5 "^7.0.0"
|
||||
|
||||
"@types/json-schema@*", "@types/json-schema@^7.0.12":
|
||||
"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.15":
|
||||
version "7.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
|
||||
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
|
||||
@@ -2921,6 +3122,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.19.tgz#ad83aa9b7af470fab7e0f562be87e97dc8ffe08e"
|
||||
integrity sha512-Sq1itGUKUX1ap7GgZlrzdBydjbsJL/NSQt/4wkAxUJ7/OS5c2WkoN6WSpWc2Yc5wtKMZOUA0VCs/j2XJadN3HA==
|
||||
|
||||
"@types/node@^20":
|
||||
version "20.17.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.10.tgz#3f7166190aece19a0d1d364d75c8b0b5778c1e18"
|
||||
integrity sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA==
|
||||
dependencies:
|
||||
undici-types "~6.19.2"
|
||||
|
||||
"@types/node@^20.2.5":
|
||||
version "20.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.2.5.tgz#26d295f3570323b2837d322180dfbf1ba156fefb"
|
||||
@@ -3003,6 +3211,21 @@
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@8.18.1":
|
||||
version "8.18.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.1.tgz#992e5ac1553ce20d0d46aa6eccd79dc36dedc805"
|
||||
integrity sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==
|
||||
dependencies:
|
||||
"@eslint-community/regexpp" "^4.10.0"
|
||||
"@typescript-eslint/scope-manager" "8.18.1"
|
||||
"@typescript-eslint/type-utils" "8.18.1"
|
||||
"@typescript-eslint/utils" "8.18.1"
|
||||
"@typescript-eslint/visitor-keys" "8.18.1"
|
||||
graphemer "^1.4.0"
|
||||
ignore "^5.3.1"
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^7.4.0":
|
||||
version "7.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz#de61c3083842fc6ac889d2fc83c9a96b55ab8328"
|
||||
@@ -3035,6 +3258,17 @@
|
||||
natural-compare "^1.4.0"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/parser@8.18.1":
|
||||
version "8.18.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.18.1.tgz#c258bae062778b7696793bc492249027a39dfb95"
|
||||
integrity sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "8.18.1"
|
||||
"@typescript-eslint/types" "8.18.1"
|
||||
"@typescript-eslint/typescript-estree" "8.18.1"
|
||||
"@typescript-eslint/visitor-keys" "8.18.1"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/parser@^7.4.0":
|
||||
version "7.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.4.0.tgz#540f4321de1e52b886c0fa68628af1459954c1f1"
|
||||
@@ -3065,6 +3299,14 @@
|
||||
"@typescript-eslint/types" "7.4.0"
|
||||
"@typescript-eslint/visitor-keys" "7.4.0"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.18.1":
|
||||
version "8.18.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.18.1.tgz#52cedc3a8178d7464a70beffed3203678648e55b"
|
||||
integrity sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.18.1"
|
||||
"@typescript-eslint/visitor-keys" "8.18.1"
|
||||
|
||||
"@typescript-eslint/scope-manager@8.7.0":
|
||||
version "8.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.7.0.tgz#90ee7bf9bc982b9260b93347c01a8bc2b595e0b8"
|
||||
@@ -3083,6 +3325,16 @@
|
||||
debug "^4.3.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
|
||||
"@typescript-eslint/type-utils@8.18.1":
|
||||
version "8.18.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.18.1.tgz#10f41285475c0bdee452b79ff7223f0e43a7781e"
|
||||
integrity sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/typescript-estree" "8.18.1"
|
||||
"@typescript-eslint/utils" "8.18.1"
|
||||
debug "^4.3.4"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/type-utils@8.7.0":
|
||||
version "8.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.7.0.tgz#d56b104183bdcffcc434a23d1ce26cde5e42df93"
|
||||
@@ -3098,6 +3350,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.4.0.tgz#ee9dafa75c99eaee49de6dcc9348b45d354419b6"
|
||||
integrity sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==
|
||||
|
||||
"@typescript-eslint/types@8.18.1":
|
||||
version "8.18.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.18.1.tgz#d7f4f94d0bba9ebd088de840266fcd45408a8fff"
|
||||
integrity sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==
|
||||
|
||||
"@typescript-eslint/types@8.7.0":
|
||||
version "8.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.7.0.tgz#21d987201c07b69ce7ddc03451d7196e5445ad19"
|
||||
@@ -3117,6 +3374,20 @@
|
||||
semver "^7.5.4"
|
||||
ts-api-utils "^1.0.1"
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.18.1":
|
||||
version "8.18.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.1.tgz#2a86cd64b211a742f78dfa7e6f4860413475367e"
|
||||
integrity sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.18.1"
|
||||
"@typescript-eslint/visitor-keys" "8.18.1"
|
||||
debug "^4.3.4"
|
||||
fast-glob "^3.3.2"
|
||||
is-glob "^4.0.3"
|
||||
minimatch "^9.0.4"
|
||||
semver "^7.6.0"
|
||||
ts-api-utils "^1.3.0"
|
||||
|
||||
"@typescript-eslint/typescript-estree@8.7.0":
|
||||
version "8.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.7.0.tgz#6c7db6baa4380b937fa81466c546d052f362d0e8"
|
||||
@@ -3144,6 +3415,16 @@
|
||||
"@typescript-eslint/typescript-estree" "7.4.0"
|
||||
semver "^7.5.4"
|
||||
|
||||
"@typescript-eslint/utils@8.18.1":
|
||||
version "8.18.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.18.1.tgz#c4199ea23fc823c736e2c96fd07b1f7235fa92d5"
|
||||
integrity sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.4.0"
|
||||
"@typescript-eslint/scope-manager" "8.18.1"
|
||||
"@typescript-eslint/types" "8.18.1"
|
||||
"@typescript-eslint/typescript-estree" "8.18.1"
|
||||
|
||||
"@typescript-eslint/utils@8.7.0":
|
||||
version "8.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.7.0.tgz#cef3f70708b5b5fd7ed8672fc14714472bd8a011"
|
||||
@@ -3162,6 +3443,14 @@
|
||||
"@typescript-eslint/types" "7.4.0"
|
||||
eslint-visitor-keys "^3.4.1"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.18.1":
|
||||
version "8.18.1"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.1.tgz#344b4f6bc83f104f514676facf3129260df7610a"
|
||||
integrity sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "8.18.1"
|
||||
eslint-visitor-keys "^4.2.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@8.7.0":
|
||||
version "8.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.7.0.tgz#5e46f1777f9d69360a883c1a56ac3c511c9659a8"
|
||||
@@ -3208,6 +3497,11 @@ acorn@^7.1.1:
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
|
||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||
|
||||
acorn@^8.14.0:
|
||||
version "8.14.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0"
|
||||
integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
|
||||
|
||||
acorn@^8.4.1, acorn@^8.7.1:
|
||||
version "8.8.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8"
|
||||
@@ -3621,11 +3915,6 @@ buffer@^5.5.0:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
builtin-modules@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"
|
||||
integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==
|
||||
|
||||
call-bind@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||
@@ -3841,6 +4130,16 @@ core-js-compat@^3.30.1, core-js-compat@^3.30.2:
|
||||
dependencies:
|
||||
browserslist "^4.21.5"
|
||||
|
||||
cosmiconfig@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d"
|
||||
integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==
|
||||
dependencies:
|
||||
env-paths "^2.2.1"
|
||||
import-fresh "^3.3.0"
|
||||
js-yaml "^4.1.0"
|
||||
parse-json "^5.2.0"
|
||||
|
||||
create-require@^1.1.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
|
||||
@@ -3855,6 +4154,15 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
cross-spawn@^7.0.6:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
|
||||
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
|
||||
dependencies:
|
||||
path-key "^3.1.0"
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
cssom@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36"
|
||||
@@ -4076,6 +4384,11 @@ entities@^4.4.0:
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174"
|
||||
integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==
|
||||
|
||||
env-paths@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
|
||||
integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
|
||||
|
||||
error-ex@^1.3.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
||||
@@ -4088,6 +4401,36 @@ es5-ext@0.8.x:
|
||||
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.8.2.tgz#aba8d9e1943a895ac96837a62a39b3f55ecd94ab"
|
||||
integrity sha512-H19ompyhnKiBdjHR1DPHvf5RHgHPmJaY9JNzFGbMbPgdsUkvnUCN1Ke8J4Y0IMyTwFM2M9l4h2GoHwzwpSmXbA==
|
||||
|
||||
esbuild@^0.24.0:
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.0.tgz#f2d470596885fcb2e91c21eb3da3b3c89c0b55e7"
|
||||
integrity sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==
|
||||
optionalDependencies:
|
||||
"@esbuild/aix-ppc64" "0.24.0"
|
||||
"@esbuild/android-arm" "0.24.0"
|
||||
"@esbuild/android-arm64" "0.24.0"
|
||||
"@esbuild/android-x64" "0.24.0"
|
||||
"@esbuild/darwin-arm64" "0.24.0"
|
||||
"@esbuild/darwin-x64" "0.24.0"
|
||||
"@esbuild/freebsd-arm64" "0.24.0"
|
||||
"@esbuild/freebsd-x64" "0.24.0"
|
||||
"@esbuild/linux-arm" "0.24.0"
|
||||
"@esbuild/linux-arm64" "0.24.0"
|
||||
"@esbuild/linux-ia32" "0.24.0"
|
||||
"@esbuild/linux-loong64" "0.24.0"
|
||||
"@esbuild/linux-mips64el" "0.24.0"
|
||||
"@esbuild/linux-ppc64" "0.24.0"
|
||||
"@esbuild/linux-riscv64" "0.24.0"
|
||||
"@esbuild/linux-s390x" "0.24.0"
|
||||
"@esbuild/linux-x64" "0.24.0"
|
||||
"@esbuild/netbsd-x64" "0.24.0"
|
||||
"@esbuild/openbsd-arm64" "0.24.0"
|
||||
"@esbuild/openbsd-x64" "0.24.0"
|
||||
"@esbuild/sunos-x64" "0.24.0"
|
||||
"@esbuild/win32-arm64" "0.24.0"
|
||||
"@esbuild/win32-ia32" "0.24.0"
|
||||
"@esbuild/win32-x64" "0.24.0"
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
@@ -4133,6 +4476,14 @@ eslint-scope@^7.2.2:
|
||||
esrecurse "^4.3.0"
|
||||
estraverse "^5.2.0"
|
||||
|
||||
eslint-scope@^8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442"
|
||||
integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==
|
||||
dependencies:
|
||||
esrecurse "^4.3.0"
|
||||
estraverse "^5.2.0"
|
||||
|
||||
eslint-visitor-keys@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
|
||||
@@ -4148,6 +4499,11 @@ eslint-visitor-keys@^3.4.3:
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint-visitor-keys@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45"
|
||||
integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==
|
||||
|
||||
eslint@8.57.0:
|
||||
version "8.57.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668"
|
||||
@@ -4236,6 +4592,55 @@ eslint@^8.57.1:
|
||||
strip-ansi "^6.0.1"
|
||||
text-table "^0.2.0"
|
||||
|
||||
eslint@^9.13.0:
|
||||
version "9.17.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.17.0.tgz#faa1facb5dd042172fdc520106984b5c2421bb0c"
|
||||
integrity sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.2.0"
|
||||
"@eslint-community/regexpp" "^4.12.1"
|
||||
"@eslint/config-array" "^0.19.0"
|
||||
"@eslint/core" "^0.9.0"
|
||||
"@eslint/eslintrc" "^3.2.0"
|
||||
"@eslint/js" "9.17.0"
|
||||
"@eslint/plugin-kit" "^0.2.3"
|
||||
"@humanfs/node" "^0.16.6"
|
||||
"@humanwhocodes/module-importer" "^1.0.1"
|
||||
"@humanwhocodes/retry" "^0.4.1"
|
||||
"@types/estree" "^1.0.6"
|
||||
"@types/json-schema" "^7.0.15"
|
||||
ajv "^6.12.4"
|
||||
chalk "^4.0.0"
|
||||
cross-spawn "^7.0.6"
|
||||
debug "^4.3.2"
|
||||
escape-string-regexp "^4.0.0"
|
||||
eslint-scope "^8.2.0"
|
||||
eslint-visitor-keys "^4.2.0"
|
||||
espree "^10.3.0"
|
||||
esquery "^1.5.0"
|
||||
esutils "^2.0.2"
|
||||
fast-deep-equal "^3.1.3"
|
||||
file-entry-cache "^8.0.0"
|
||||
find-up "^5.0.0"
|
||||
glob-parent "^6.0.2"
|
||||
ignore "^5.2.0"
|
||||
imurmurhash "^0.1.4"
|
||||
is-glob "^4.0.0"
|
||||
json-stable-stringify-without-jsonify "^1.0.1"
|
||||
lodash.merge "^4.6.2"
|
||||
minimatch "^3.1.2"
|
||||
natural-compare "^1.4.0"
|
||||
optionator "^0.9.3"
|
||||
|
||||
espree@^10.0.1, espree@^10.3.0:
|
||||
version "10.3.0"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a"
|
||||
integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==
|
||||
dependencies:
|
||||
acorn "^8.14.0"
|
||||
acorn-jsx "^5.3.2"
|
||||
eslint-visitor-keys "^4.2.0"
|
||||
|
||||
espree@^9.6.0, espree@^9.6.1:
|
||||
version "9.6.1"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
|
||||
@@ -4257,6 +4662,13 @@ esquery@^1.4.2:
|
||||
dependencies:
|
||||
estraverse "^5.1.0"
|
||||
|
||||
esquery@^1.5.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7"
|
||||
integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==
|
||||
dependencies:
|
||||
estraverse "^5.1.0"
|
||||
|
||||
esrecurse@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
|
||||
@@ -4408,6 +4820,11 @@ fbt@^1.0.2:
|
||||
dependencies:
|
||||
invariant "^2.2.4"
|
||||
|
||||
fdir@^6.2.0:
|
||||
version "6.4.2"
|
||||
resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.2.tgz#ddaa7ce1831b161bc3657bb99cb36e1622702689"
|
||||
integrity sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==
|
||||
|
||||
file-entry-cache@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
|
||||
@@ -4415,6 +4832,13 @@ file-entry-cache@^6.0.1:
|
||||
dependencies:
|
||||
flat-cache "^3.0.4"
|
||||
|
||||
file-entry-cache@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f"
|
||||
integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==
|
||||
dependencies:
|
||||
flat-cache "^4.0.0"
|
||||
|
||||
fill-range@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
|
||||
@@ -4462,11 +4886,24 @@ flat-cache@^3.0.4:
|
||||
flatted "^3.1.0"
|
||||
rimraf "^3.0.2"
|
||||
|
||||
flat-cache@^4.0.0:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c"
|
||||
integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==
|
||||
dependencies:
|
||||
flatted "^3.2.9"
|
||||
keyv "^4.5.4"
|
||||
|
||||
flatted@^3.1.0:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
|
||||
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
|
||||
|
||||
flatted@^3.2.9:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27"
|
||||
integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==
|
||||
|
||||
flow-enums-runtime@^0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/flow-enums-runtime/-/flow-enums-runtime-0.0.4.tgz#038635c679030d08d4c197db29a2fad62722072f"
|
||||
@@ -4592,17 +5029,6 @@ glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^8.0.3:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
|
||||
integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^5.0.1"
|
||||
once "^1.3.0"
|
||||
|
||||
globals@^11.1.0:
|
||||
version "11.12.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
||||
@@ -4615,6 +5041,11 @@ globals@^13.19.0:
|
||||
dependencies:
|
||||
type-fest "^0.20.2"
|
||||
|
||||
globals@^14.0.0:
|
||||
version "14.0.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e"
|
||||
integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==
|
||||
|
||||
globby@^11.1.0:
|
||||
version "11.1.0"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
|
||||
@@ -4758,7 +5189,7 @@ ignore@^5.3.1:
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
|
||||
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
|
||||
|
||||
import-fresh@^3.2.1:
|
||||
import-fresh@^3.2.1, import-fresh@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
|
||||
integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
|
||||
@@ -4804,13 +5235,6 @@ is-arrayish@^0.2.1:
|
||||
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
|
||||
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
|
||||
|
||||
is-builtin-module@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169"
|
||||
integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==
|
||||
dependencies:
|
||||
builtin-modules "^3.3.0"
|
||||
|
||||
is-core-module@^2.11.0:
|
||||
version "2.12.1"
|
||||
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd"
|
||||
@@ -6154,6 +6578,11 @@ jsesc@~0.5.0:
|
||||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
|
||||
integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==
|
||||
|
||||
json-buffer@3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
|
||||
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
|
||||
|
||||
json-diff@^0.5.4:
|
||||
version "0.5.5"
|
||||
resolved "https://registry.yarnpkg.com/json-diff/-/json-diff-0.5.5.tgz#24658ad200dbdd64ae8a56baf4d87b2b33d7196e"
|
||||
@@ -6195,6 +6624,13 @@ keypress@~0.2.1:
|
||||
resolved "https://registry.yarnpkg.com/keypress/-/keypress-0.2.1.tgz#1e80454250018dbad4c3fe94497d6e67b6269c77"
|
||||
integrity sha512-HjorDJFNhnM4SicvaUXac0X77NiskggxJdesG72+O5zBKpSqKFCrqmndKVqpu3pFqkla0St6uGk8Ju0sCurrmg==
|
||||
|
||||
keyv@^4.5.4:
|
||||
version "4.5.4"
|
||||
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
|
||||
integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
|
||||
dependencies:
|
||||
json-buffer "3.0.1"
|
||||
|
||||
kind-of@^6.0.2:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
|
||||
@@ -6429,13 +6865,6 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimatch@^5.0.1, minimatch@~5.1.2:
|
||||
version "5.1.6"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
|
||||
integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@^9.0.4:
|
||||
version "9.0.5"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
|
||||
@@ -6443,6 +6872,13 @@ minimatch@^9.0.4:
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimatch@~5.1.2:
|
||||
version "5.1.6"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
|
||||
integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
minimist@^1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||
@@ -6724,6 +7160,11 @@ picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1:
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
picomatch@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab"
|
||||
integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==
|
||||
|
||||
pify@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
|
||||
@@ -7576,11 +8017,25 @@ type-fest@^0.21.3:
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
|
||||
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
|
||||
|
||||
typescript-eslint@^8.16.0:
|
||||
version "8.18.1"
|
||||
resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.18.1.tgz#197b284b6769678ed77d9868df180eeaf61108eb"
|
||||
integrity sha512-Mlaw6yxuaDEPQvb/2Qwu3/TfgeBHy9iTJ3mTwe7OvpPmF6KPQjVOfGyEJpPv6Ez2C34OODChhXrzYw/9phI0MQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/eslint-plugin" "8.18.1"
|
||||
"@typescript-eslint/parser" "8.18.1"
|
||||
"@typescript-eslint/utils" "8.18.1"
|
||||
|
||||
typescript@^5.4.3:
|
||||
version "5.4.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff"
|
||||
integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==
|
||||
|
||||
undici-types@~6.19.2:
|
||||
version "6.19.8"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
|
||||
integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
|
||||
|
||||
unicode-canonical-property-names-ecmascript@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc"
|
||||
|
||||
@@ -14,8 +14,6 @@ let TestAct;
|
||||
|
||||
global.__DEV__ = process.env.NODE_ENV !== 'production';
|
||||
|
||||
expect.extend(require('../toWarnDev'));
|
||||
|
||||
describe('unmocked scheduler', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
|
||||
@@ -1,284 +0,0 @@
|
||||
// copied from scripts/jest/matchers/toWarnDev.js
|
||||
'use strict';
|
||||
|
||||
const {diff: jestDiff} = require('jest-diff');
|
||||
const util = require('util');
|
||||
|
||||
function shouldIgnoreConsoleError(format, args) {
|
||||
if (__DEV__) {
|
||||
if (typeof format === 'string') {
|
||||
if (format.indexOf('The above error occurred') === 0) {
|
||||
// This looks like an error addendum from ReactFiberErrorLogger.
|
||||
// Ignore it too.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
format != null &&
|
||||
typeof format.message === 'string' &&
|
||||
typeof format.stack === 'string' &&
|
||||
args.length === 0
|
||||
) {
|
||||
// In production, ReactFiberErrorLogger logs error objects directly.
|
||||
// They are noisy too so we'll try to ignore them.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Looks legit
|
||||
return false;
|
||||
}
|
||||
|
||||
function normalizeCodeLocInfo(str) {
|
||||
return str && str.replace(/at .+?:\d+/g, 'at **');
|
||||
}
|
||||
|
||||
const createMatcherFor = consoleMethod =>
|
||||
function matcher(callback, expectedMessages, options = {}) {
|
||||
if (__DEV__) {
|
||||
// Warn about incorrect usage of matcher.
|
||||
if (typeof expectedMessages === 'string') {
|
||||
expectedMessages = [expectedMessages];
|
||||
} else if (!Array.isArray(expectedMessages)) {
|
||||
throw Error(
|
||||
`toWarnDev() requires a parameter of type string or an array of strings ` +
|
||||
`but was given ${typeof expectedMessages}.`
|
||||
);
|
||||
}
|
||||
if (
|
||||
options != null &&
|
||||
(typeof options !== 'object' || Array.isArray(options))
|
||||
) {
|
||||
throw new Error(
|
||||
'toWarnDev() second argument, when present, should be an object. ' +
|
||||
'Did you forget to wrap the messages into an array?'
|
||||
);
|
||||
}
|
||||
if (arguments.length > 3) {
|
||||
// `matcher` comes from Jest, so it's more than 2 in practice
|
||||
throw new Error(
|
||||
'toWarnDev() received more than two arguments. ' +
|
||||
'Did you forget to wrap the messages into an array?'
|
||||
);
|
||||
}
|
||||
|
||||
const withoutStack = options.withoutStack;
|
||||
const warningsWithoutComponentStack = [];
|
||||
const warningsWithComponentStack = [];
|
||||
const unexpectedWarnings = [];
|
||||
|
||||
let lastWarningWithMismatchingFormat = null;
|
||||
let lastWarningWithExtraComponentStack = null;
|
||||
|
||||
// Catch errors thrown by the callback,
|
||||
// But only rethrow them if all test expectations have been satisfied.
|
||||
// Otherwise an Error in the callback can mask a failed expectation,
|
||||
// and result in a test that passes when it shouldn't.
|
||||
let caughtError;
|
||||
|
||||
const isLikelyAComponentStack = message =>
|
||||
typeof message === 'string' && message.includes('\n in ');
|
||||
|
||||
const consoleSpy = (format, ...args) => {
|
||||
// Ignore uncaught errors reported by jsdom
|
||||
// and React addendums because they're too noisy.
|
||||
if (
|
||||
consoleMethod === 'error' &&
|
||||
shouldIgnoreConsoleError(format, args)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const message = util.format(format, ...args);
|
||||
const normalizedMessage = normalizeCodeLocInfo(message);
|
||||
|
||||
// Remember if the number of %s interpolations
|
||||
// doesn't match the number of arguments.
|
||||
// We'll fail the test if it happens.
|
||||
let argIndex = 0;
|
||||
format.replace(/%s/g, () => argIndex++);
|
||||
if (argIndex !== args.length) {
|
||||
lastWarningWithMismatchingFormat = {
|
||||
format,
|
||||
args,
|
||||
expectedArgCount: argIndex,
|
||||
};
|
||||
}
|
||||
|
||||
// Protect against accidentally passing a component stack
|
||||
// to warning() which already injects the component stack.
|
||||
if (
|
||||
args.length >= 2 &&
|
||||
isLikelyAComponentStack(args[args.length - 1]) &&
|
||||
isLikelyAComponentStack(args[args.length - 2])
|
||||
) {
|
||||
lastWarningWithExtraComponentStack = {
|
||||
format,
|
||||
};
|
||||
}
|
||||
|
||||
for (let index = 0; index < expectedMessages.length; index++) {
|
||||
const expectedMessage = expectedMessages[index];
|
||||
if (
|
||||
normalizedMessage === expectedMessage ||
|
||||
normalizedMessage.includes(expectedMessage)
|
||||
) {
|
||||
if (isLikelyAComponentStack(normalizedMessage)) {
|
||||
warningsWithComponentStack.push(normalizedMessage);
|
||||
} else {
|
||||
warningsWithoutComponentStack.push(normalizedMessage);
|
||||
}
|
||||
expectedMessages.splice(index, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let errorMessage;
|
||||
if (expectedMessages.length === 0) {
|
||||
errorMessage =
|
||||
'Unexpected warning recorded: ' +
|
||||
this.utils.printReceived(normalizedMessage);
|
||||
} else if (expectedMessages.length === 1) {
|
||||
errorMessage =
|
||||
'Unexpected warning recorded: ' +
|
||||
jestDiff(expectedMessages[0], normalizedMessage);
|
||||
} else {
|
||||
errorMessage =
|
||||
'Unexpected warning recorded: ' +
|
||||
jestDiff(expectedMessages, [normalizedMessage]);
|
||||
}
|
||||
|
||||
// Record the call stack for unexpected warnings.
|
||||
// We don't throw an Error here though,
|
||||
// Because it might be suppressed by ReactFiberScheduler.
|
||||
unexpectedWarnings.push(new Error(errorMessage));
|
||||
};
|
||||
|
||||
// TODO Decide whether we need to support nested toWarn* expectations.
|
||||
// If we don't need it, add a check here to see if this is already our spy,
|
||||
// And throw an error.
|
||||
const originalMethod = console[consoleMethod];
|
||||
|
||||
// Avoid using Jest's built-in spy since it can't be removed.
|
||||
console[consoleMethod] = consoleSpy;
|
||||
|
||||
try {
|
||||
callback();
|
||||
} catch (error) {
|
||||
caughtError = error;
|
||||
} finally {
|
||||
// Restore the unspied method so that unexpected errors fail tests.
|
||||
console[consoleMethod] = originalMethod;
|
||||
|
||||
// Any unexpected Errors thrown by the callback should fail the test.
|
||||
// This should take precedence since unexpected errors could block warnings.
|
||||
if (caughtError) {
|
||||
throw caughtError;
|
||||
}
|
||||
|
||||
// Any unexpected warnings should be treated as a failure.
|
||||
if (unexpectedWarnings.length > 0) {
|
||||
return {
|
||||
message: () => unexpectedWarnings[0].stack,
|
||||
pass: false,
|
||||
};
|
||||
}
|
||||
|
||||
// Any remaining messages indicate a failed expectations.
|
||||
if (expectedMessages.length > 0) {
|
||||
return {
|
||||
message: () =>
|
||||
`Expected warning was not recorded:\n ${this.utils.printReceived(
|
||||
expectedMessages[0]
|
||||
)}`,
|
||||
pass: false,
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof withoutStack === 'number') {
|
||||
// We're expecting a particular number of warnings without stacks.
|
||||
if (withoutStack !== warningsWithoutComponentStack.length) {
|
||||
return {
|
||||
message: () =>
|
||||
`Expected ${withoutStack} warnings without a component stack but received ${warningsWithoutComponentStack.length}:\n` +
|
||||
warningsWithoutComponentStack.map(warning =>
|
||||
this.utils.printReceived(warning)
|
||||
),
|
||||
pass: false,
|
||||
};
|
||||
}
|
||||
} else if (withoutStack === true) {
|
||||
// We're expecting that all warnings won't have the stack.
|
||||
// If some warnings have it, it's an error.
|
||||
if (warningsWithComponentStack.length > 0) {
|
||||
return {
|
||||
message: () =>
|
||||
`Received warning unexpectedly includes a component stack:\n ${this.utils.printReceived(
|
||||
warningsWithComponentStack[0]
|
||||
)}\nIf this warning intentionally includes the component stack, remove ` +
|
||||
`{withoutStack: true} from the toWarnDev() call. If you have a mix of ` +
|
||||
`warnings with and without stack in one toWarnDev() call, pass ` +
|
||||
`{withoutStack: N} where N is the number of warnings without stacks.`,
|
||||
pass: false,
|
||||
};
|
||||
}
|
||||
} else if (withoutStack === false || withoutStack === undefined) {
|
||||
// We're expecting that all warnings *do* have the stack (default).
|
||||
// If some warnings don't have it, it's an error.
|
||||
if (warningsWithoutComponentStack.length > 0) {
|
||||
return {
|
||||
message: () =>
|
||||
`Received warning unexpectedly does not include a component stack:\n ${this.utils.printReceived(
|
||||
warningsWithoutComponentStack[0]
|
||||
)}\nIf this warning intentionally omits the component stack, add ` +
|
||||
`{withoutStack: true} to the toWarnDev() call.`,
|
||||
pass: false,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
throw Error(
|
||||
`The second argument for toWarnDev(), when specified, must be an object. It may have a ` +
|
||||
`property called "withoutStack" whose value may be undefined, boolean, or a number. ` +
|
||||
`Instead received ${typeof withoutStack}.`
|
||||
);
|
||||
}
|
||||
|
||||
if (lastWarningWithMismatchingFormat !== null) {
|
||||
return {
|
||||
message: () =>
|
||||
`Received ${
|
||||
lastWarningWithMismatchingFormat.args.length
|
||||
} arguments for a message with ${
|
||||
lastWarningWithMismatchingFormat.expectedArgCount
|
||||
} placeholders:\n ${this.utils.printReceived(
|
||||
lastWarningWithMismatchingFormat.format
|
||||
)}`,
|
||||
pass: false,
|
||||
};
|
||||
}
|
||||
|
||||
if (lastWarningWithExtraComponentStack !== null) {
|
||||
return {
|
||||
message: () =>
|
||||
`Received more than one component stack for a warning:\n ${this.utils.printReceived(
|
||||
lastWarningWithExtraComponentStack.format
|
||||
)}\nDid you accidentally pass a stack to warning() as the last argument? ` +
|
||||
`Don't forget warning() already injects the component stack automatically.`,
|
||||
pass: false,
|
||||
};
|
||||
}
|
||||
|
||||
return {pass: true};
|
||||
}
|
||||
} else {
|
||||
// Any uncaught errors or warnings should fail tests in production mode.
|
||||
callback();
|
||||
|
||||
return {pass: true};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
toLowPriorityWarnDev: createMatcherFor('warn'),
|
||||
toWarnDev: createMatcherFor('error'),
|
||||
};
|
||||
@@ -22,6 +22,7 @@ let waitForPaint;
|
||||
let assertLog;
|
||||
let waitForThrow;
|
||||
let act;
|
||||
let assertConsoleErrorDev;
|
||||
|
||||
describe('ReactCache', () => {
|
||||
beforeEach(() => {
|
||||
@@ -39,6 +40,7 @@ describe('ReactCache', () => {
|
||||
assertLog = InternalTestUtils.assertLog;
|
||||
waitForThrow = InternalTestUtils.waitForThrow;
|
||||
waitForPaint = InternalTestUtils.waitForPaint;
|
||||
assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;
|
||||
act = InternalTestUtils.act;
|
||||
|
||||
TextResource = createResource(
|
||||
@@ -190,20 +192,31 @@ describe('ReactCache', () => {
|
||||
);
|
||||
|
||||
if (__DEV__) {
|
||||
await expect(async () => {
|
||||
await waitForAll([
|
||||
'App',
|
||||
'Loading...',
|
||||
await waitForAll([
|
||||
'App',
|
||||
'Loading...',
|
||||
|
||||
...(gate('enableSiblingPrerendering') ? ['App'] : []),
|
||||
]);
|
||||
}).toErrorDev([
|
||||
...(gate('enableSiblingPrerendering') ? ['App'] : []),
|
||||
]);
|
||||
assertConsoleErrorDev([
|
||||
'Invalid key type. Expected a string, number, symbol, or ' +
|
||||
"boolean, but instead received: [ 'Hi', 100 ]\n\n" +
|
||||
'To use non-primitive values as keys, you must pass a hash ' +
|
||||
'function as the second argument to createResource().',
|
||||
'function as the second argument to createResource().\n' +
|
||||
' in App (at **)' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in Suspense (at **)'),
|
||||
|
||||
...(gate('enableSiblingPrerendering') ? ['Invalid key type'] : []),
|
||||
...(gate('enableSiblingPrerendering')
|
||||
? [
|
||||
'Invalid key type. Expected a string, number, symbol, or ' +
|
||||
"boolean, but instead received: [ 'Hi', 100 ]\n\n" +
|
||||
'To use non-primitive values as keys, you must pass a hash ' +
|
||||
'function as the second argument to createResource().\n' +
|
||||
' in App (at **)',
|
||||
]
|
||||
: []),
|
||||
]);
|
||||
} else {
|
||||
await waitForAll([
|
||||
|
||||
+474
-166
@@ -1467,13 +1467,12 @@ describe('ReactFlight', () => {
|
||||
|
||||
const transport = ReactNoopFlightServer.render(<App />);
|
||||
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
startTransition(() => {
|
||||
ReactNoop.render(ReactNoopFlightClient.read(transport));
|
||||
});
|
||||
await act(() => {
|
||||
startTransition(() => {
|
||||
ReactNoop.render(ReactNoopFlightClient.read(transport));
|
||||
});
|
||||
}).toErrorDev(
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n' +
|
||||
'\n' +
|
||||
'Check the render method of `Component`. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
@@ -1483,7 +1482,7 @@ describe('ReactFlight', () => {
|
||||
? ''
|
||||
: ' in Indirection (at **)\n') +
|
||||
' in App (at **)',
|
||||
);
|
||||
]);
|
||||
});
|
||||
|
||||
it('should trigger the inner most error boundary inside a Client Component', async () => {
|
||||
@@ -1541,17 +1540,47 @@ describe('ReactFlight', () => {
|
||||
return 123;
|
||||
},
|
||||
};
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(<input value={obj} />);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <input value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
{withoutStack: true},
|
||||
);
|
||||
const transport = ReactNoopFlightServer.render(<input value={obj} />);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <input value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <input value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <input value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <input value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a toJSON instance is passed to a host component child', () => {
|
||||
@@ -1560,43 +1589,123 @@ describe('ReactFlight', () => {
|
||||
return 123;
|
||||
}
|
||||
}
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<div>Womp womp: {new MyError('spaghetti')}</div>,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
{withoutStack: true},
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<div>Womp womp: {new MyError('spaghetti')}</div>,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
'Error objects cannot be rendered as text children. Try formatting it using toString().\n' +
|
||||
' <div>Womp womp: {Error}</div>\n' +
|
||||
' ^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a special object is passed to a host component', () => {
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(<input value={Math} />);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
{withoutStack: true},
|
||||
);
|
||||
const transport = ReactNoopFlightServer.render(<input value={Math} />);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <input value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if an object with symbols is passed to a host component', () => {
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<input value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.',
|
||||
{withoutStack: true},
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<input value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <input value={{}}>\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <input value={{}}>\n' +
|
||||
' ^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <input value={{}}>\n' +
|
||||
' ^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <input value={{}}>\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a toJSON instance is passed to a Client Component', () => {
|
||||
@@ -1609,14 +1718,47 @@ describe('ReactFlight', () => {
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(<Client value={obj} />);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported.',
|
||||
{withoutStack: true},
|
||||
);
|
||||
const transport = ReactNoopFlightServer.render(<Client value={obj} />);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <... value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <... value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <... value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <... value={{toJSON: ...}}>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a toJSON instance is passed to a Client Component child', () => {
|
||||
@@ -1629,19 +1771,49 @@ describe('ReactFlight', () => {
|
||||
return <div>{children}</div>;
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client>Current date: {obj}</Client>,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
{withoutStack: true},
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client>Current date: {obj}</Client>,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||
' ^^^^^^^^^^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with toJSON methods are not supported. ' +
|
||||
'Convert it manually to a simple value before passing it to props.\n' +
|
||||
' <>Current date: {{toJSON: ...}}</>\n' +
|
||||
' ^^^^^^^^^^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a special object is passed to a Client Component', () => {
|
||||
@@ -1649,16 +1821,44 @@ describe('ReactFlight', () => {
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(<Client value={Math} />);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
{withoutStack: true},
|
||||
);
|
||||
const transport = ReactNoopFlightServer.render(<Client value={Math} />);
|
||||
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' <... value={Math}>\n' +
|
||||
' ^^^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if an object with symbols is passed to a Client Component', () => {
|
||||
@@ -1666,16 +1866,46 @@ describe('ReactFlight', () => {
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.',
|
||||
{withoutStack: true},
|
||||
assertConsoleErrorDev([]);
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
|
||||
ReactNoopFlightClient.read(transport);
|
||||
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^\n',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a special object is passed to a nested object in Client Component', () => {
|
||||
@@ -1683,18 +1913,41 @@ describe('ReactFlight', () => {
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client value={{hello: Math, title: <h1>hi</h1>}} />,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' {hello: Math, title: <h1/>}\n' +
|
||||
' ^^^^',
|
||||
{withoutStack: true},
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client value={{[Symbol.iterator]: {}}} />,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Objects with symbol properties like Symbol.iterator are not supported.\n' +
|
||||
' <... value={{}}>\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV if a special object is passed to a nested array in Client Component', () => {
|
||||
@@ -1702,20 +1955,40 @@ describe('ReactFlight', () => {
|
||||
return <div>{value}</div>;
|
||||
}
|
||||
const Client = clientReference(ClientImpl);
|
||||
expect(() => {
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client
|
||||
value={['looooong string takes up noise', Math, <h1>hi</h1>]}
|
||||
/>,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev(
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^',
|
||||
{withoutStack: true},
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Client value={['looooong string takes up noise', Math, <h1>hi</h1>]} />,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^',
|
||||
{withoutStack: true},
|
||||
],
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^\n' +
|
||||
' at (<anonymous>)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^',
|
||||
'Only plain objects can be passed to Client Components from Server Components. ' +
|
||||
'Math objects are not supported.\n' +
|
||||
' [..., Math, <h1/>]\n' +
|
||||
' ^^^^',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('should NOT warn in DEV for key getters', () => {
|
||||
@@ -1729,63 +2002,100 @@ describe('ReactFlight', () => {
|
||||
key: "this has a key but parent doesn't",
|
||||
});
|
||||
}
|
||||
expect(() => {
|
||||
// While we're on the server we need to have the Server version active to track component stacks.
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => ReactServer);
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
ReactServer.createElement(
|
||||
'div',
|
||||
null,
|
||||
Array(6).fill(ReactServer.createElement(NoKey)),
|
||||
),
|
||||
);
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => React);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev('Each child in a list should have a unique "key" prop.');
|
||||
// While we're on the server we need to have the Server version active to track component stacks.
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => ReactServer);
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
ReactServer.createElement(
|
||||
'div',
|
||||
null,
|
||||
Array(6).fill(ReactServer.createElement(NoKey)),
|
||||
),
|
||||
);
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => React);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in NoKey (at **)',
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in NoKey (at **)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <div>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in NoKey (at **)',
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
// @gate !__DEV__ || enableOwnerStacks
|
||||
it('should warn in DEV a child is missing keys on a fragment', () => {
|
||||
expect(() => {
|
||||
// While we're on the server we need to have the Server version active to track component stacks.
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => ReactServer);
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
ReactServer.createElement(
|
||||
'div',
|
||||
null,
|
||||
Array(6).fill(ReactServer.createElement(ReactServer.Fragment)),
|
||||
),
|
||||
);
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => React);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
}).toErrorDev('Each child in a list should have a unique "key" prop.');
|
||||
// While we're on the server we need to have the Server version active to track component stacks.
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => ReactServer);
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
ReactServer.createElement(
|
||||
'div',
|
||||
null,
|
||||
Array(6).fill(ReactServer.createElement(ReactServer.Fragment)),
|
||||
),
|
||||
);
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => React);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Fragment (at **)',
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Fragment (at **)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <div>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in Fragment (at **)',
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
it('should warn in DEV a child is missing keys in client component', async () => {
|
||||
function ParentClient({children}) {
|
||||
return children;
|
||||
}
|
||||
const Parent = clientReference(ParentClient);
|
||||
await expect(async () => {
|
||||
|
||||
await act(async () => {
|
||||
const Parent = clientReference(ParentClient);
|
||||
const transport = ReactNoopFlightServer.render(
|
||||
<Parent>{Array(6).fill(<div>no key</div>)}</Parent>,
|
||||
);
|
||||
ReactNoopFlightClient.read(transport);
|
||||
await act(async () => {
|
||||
ReactNoop.render(await ReactNoopFlightClient.read(transport));
|
||||
});
|
||||
}).toErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? 'Each child in a list should have a unique "key" prop.' +
|
||||
'\n\nCheck the top-level render call using <ParentClient>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.'
|
||||
: 'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.',
|
||||
);
|
||||
|
||||
ReactNoop.render(await ReactNoopFlightClient.read(transport));
|
||||
});
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ParentClient>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
} else {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
it('should error if a class instance is passed to a host component', () => {
|
||||
@@ -3135,19 +3445,17 @@ describe('ReactFlight', () => {
|
||||
},
|
||||
);
|
||||
|
||||
let transport;
|
||||
expect(() => {
|
||||
// Reset the modules so that we get a new overridden console on top of the
|
||||
// one installed by expect. This ensures that we still emit console.error
|
||||
// calls.
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => require('react/react.react-server'));
|
||||
ReactServer = require('react');
|
||||
ReactNoopFlightServer = require('react-noop-renderer/flight-server');
|
||||
transport = ReactNoopFlightServer.render({
|
||||
root: ReactServer.createElement(App),
|
||||
});
|
||||
}).toErrorDev('err');
|
||||
// Reset the modules so that we get a new overridden console on top of the
|
||||
// one installed by expect. This ensures that we still emit console.error
|
||||
// calls.
|
||||
jest.resetModules();
|
||||
jest.mock('react', () => require('react/react.react-server'));
|
||||
ReactServer = require('react');
|
||||
ReactNoopFlightServer = require('react-noop-renderer/flight-server');
|
||||
const transport = ReactNoopFlightServer.render({
|
||||
root: ReactServer.createElement(App),
|
||||
});
|
||||
assertConsoleErrorDev(['Error: err']);
|
||||
|
||||
expect(mockConsoleLog).toHaveBeenCalledTimes(1);
|
||||
expect(mockConsoleLog.mock.calls[0][0]).toBe('hi');
|
||||
|
||||
+8
-5
@@ -14,6 +14,7 @@ let React;
|
||||
let ReactTestRenderer;
|
||||
let ReactDebugTools;
|
||||
let act;
|
||||
let assertConsoleErrorDev;
|
||||
let useMemoCache;
|
||||
|
||||
function normalizeSourceLoc(tree) {
|
||||
@@ -33,7 +34,7 @@ describe('ReactHooksInspectionIntegration', () => {
|
||||
jest.resetModules();
|
||||
React = require('react');
|
||||
ReactTestRenderer = require('react-test-renderer');
|
||||
act = require('internal-test-utils').act;
|
||||
({act, assertConsoleErrorDev} = require('internal-test-utils'));
|
||||
ReactDebugTools = require('react-debug-tools');
|
||||
useMemoCache = require('react/compiler-runtime').c;
|
||||
});
|
||||
@@ -2344,10 +2345,12 @@ describe('ReactHooksInspectionIntegration', () => {
|
||||
</Suspense>,
|
||||
);
|
||||
|
||||
await expect(async () => {
|
||||
await act(async () => await LazyFoo);
|
||||
}).toErrorDev([
|
||||
'Foo: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.',
|
||||
await act(async () => await LazyFoo);
|
||||
assertConsoleErrorDev([
|
||||
'Foo: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.' +
|
||||
(gate(flags => flags.enableOwnerStacks)
|
||||
? ''
|
||||
: '\n in Foo (at **)\n' + ' in Suspense (at **)'),
|
||||
]);
|
||||
|
||||
const childFiber = renderer.root._currentFiber();
|
||||
|
||||
@@ -14,6 +14,7 @@ describe('when Trusted Types are available in global object', () => {
|
||||
let ReactDOMClient;
|
||||
let ReactFeatureFlags;
|
||||
let act;
|
||||
let assertConsoleErrorDev;
|
||||
let container;
|
||||
let ttObject1;
|
||||
let ttObject2;
|
||||
@@ -36,7 +37,7 @@ describe('when Trusted Types are available in global object', () => {
|
||||
ReactFeatureFlags.enableTrustedTypesIntegration = true;
|
||||
React = require('react');
|
||||
ReactDOMClient = require('react-dom/client');
|
||||
act = require('internal-test-utils').act;
|
||||
({act, assertConsoleErrorDev} = require('internal-test-utils'));
|
||||
ttObject1 = {
|
||||
toString() {
|
||||
return '<b>Hi</b>';
|
||||
@@ -208,17 +209,16 @@ describe('when Trusted Types are available in global object', () => {
|
||||
|
||||
it('should warn once when rendering script tag in jsx on client', async () => {
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render(<script>alert("I am not executed")</script>);
|
||||
});
|
||||
}).toErrorDev(
|
||||
await act(() => {
|
||||
root.render(<script>alert("I am not executed")</script>);
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
'Encountered a script tag while rendering React component. ' +
|
||||
'Scripts inside React components are never executed when rendering ' +
|
||||
'on the client. Consider using template tag instead ' +
|
||||
'(https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).\n' +
|
||||
' in script (at **)',
|
||||
);
|
||||
]);
|
||||
|
||||
// check that the warning is printed only once
|
||||
await act(() => {
|
||||
|
||||
@@ -16,6 +16,7 @@ let ReactNativePrivateInterface;
|
||||
let createReactNativeComponentClass;
|
||||
let StrictMode;
|
||||
let act;
|
||||
let assertConsoleErrorDev;
|
||||
|
||||
const DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT =
|
||||
"dispatchCommand was called with a ref that isn't a " +
|
||||
@@ -38,7 +39,7 @@ describe('ReactFabric', () => {
|
||||
createReactNativeComponentClass =
|
||||
require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface')
|
||||
.ReactNativeViewConfigRegistry.register;
|
||||
act = require('internal-test-utils').act;
|
||||
({act, assertConsoleErrorDev} = require('internal-test-utils'));
|
||||
});
|
||||
|
||||
it('should be able to create and render a native component', async () => {
|
||||
@@ -459,9 +460,8 @@ describe('ReactFabric', () => {
|
||||
});
|
||||
|
||||
expect(nativeFabricUIManager.dispatchCommand).not.toBeCalled();
|
||||
expect(() => {
|
||||
ReactFabric.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
|
||||
}).toErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT], {
|
||||
ReactFabric.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
|
||||
assertConsoleErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT], {
|
||||
withoutStack: true,
|
||||
});
|
||||
|
||||
@@ -525,9 +525,8 @@ describe('ReactFabric', () => {
|
||||
});
|
||||
|
||||
expect(nativeFabricUIManager.sendAccessibilityEvent).not.toBeCalled();
|
||||
expect(() => {
|
||||
ReactFabric.sendAccessibilityEvent(viewRef, 'eventTypeName');
|
||||
}).toErrorDev([SEND_ACCESSIBILITY_EVENT_REQUIRES_HOST_COMPONENT], {
|
||||
ReactFabric.sendAccessibilityEvent(viewRef, 'eventTypeName');
|
||||
assertConsoleErrorDev([SEND_ACCESSIBILITY_EVENT_REQUIRES_HOST_COMPONENT], {
|
||||
withoutStack: true,
|
||||
});
|
||||
|
||||
@@ -856,24 +855,31 @@ describe('ReactFabric', () => {
|
||||
uiViewClassName: 'RCTView',
|
||||
}));
|
||||
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
ReactFabric.render(<View>this should warn</View>, 11, null, true);
|
||||
});
|
||||
}).toErrorDev(['Text strings must be rendered within a <Text> component.']);
|
||||
await act(() => {
|
||||
ReactFabric.render(<View>this should warn</View>, 11, null, true);
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
'Text strings must be rendered within a <Text> component.\n' +
|
||||
' in RCTView (at **)',
|
||||
]);
|
||||
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
ReactFabric.render(
|
||||
<Text>
|
||||
<ScrollView>hi hello hi</ScrollView>
|
||||
</Text>,
|
||||
11,
|
||||
null,
|
||||
true,
|
||||
);
|
||||
});
|
||||
}).toErrorDev(['Text strings must be rendered within a <Text> component.']);
|
||||
await act(() => {
|
||||
ReactFabric.render(
|
||||
<Text>
|
||||
<ScrollView>hi hello hi</ScrollView>
|
||||
</Text>,
|
||||
11,
|
||||
null,
|
||||
true,
|
||||
);
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
'Text strings must be rendered within a <Text> component.\n' +
|
||||
' in RCTScrollView (at **)' +
|
||||
(gate(flags => !flags.enableOwnerStacks)
|
||||
? '\n in RCTText (at **)'
|
||||
: ''),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not throw for text inside of an indirect <Text> ancestor', async () => {
|
||||
@@ -1166,10 +1172,8 @@ describe('ReactFabric', () => {
|
||||
);
|
||||
});
|
||||
|
||||
let match;
|
||||
expect(
|
||||
() => (match = ReactFabric.findHostInstance_DEPRECATED(parent)),
|
||||
).toErrorDev([
|
||||
const match = ReactFabric.findHostInstance_DEPRECATED(parent);
|
||||
assertConsoleErrorDev([
|
||||
'findHostInstance_DEPRECATED is deprecated in StrictMode. ' +
|
||||
'findHostInstance_DEPRECATED was passed an instance of ContainsStrictModeChild which renders StrictMode children. ' +
|
||||
'Instead, add a ref directly to the element you want to reference. ' +
|
||||
@@ -1207,10 +1211,8 @@ describe('ReactFabric', () => {
|
||||
);
|
||||
});
|
||||
|
||||
let match;
|
||||
expect(
|
||||
() => (match = ReactFabric.findHostInstance_DEPRECATED(parent)),
|
||||
).toErrorDev([
|
||||
const match = ReactFabric.findHostInstance_DEPRECATED(parent);
|
||||
assertConsoleErrorDev([
|
||||
'findHostInstance_DEPRECATED is deprecated in StrictMode. ' +
|
||||
'findHostInstance_DEPRECATED was passed an instance of IsInStrictMode which is inside StrictMode. ' +
|
||||
'Instead, add a ref directly to the element you want to reference. ' +
|
||||
@@ -1250,8 +1252,8 @@ describe('ReactFabric', () => {
|
||||
);
|
||||
});
|
||||
|
||||
let match;
|
||||
expect(() => (match = ReactFabric.findNodeHandle(parent))).toErrorDev([
|
||||
const match = ReactFabric.findNodeHandle(parent);
|
||||
assertConsoleErrorDev([
|
||||
'findNodeHandle is deprecated in StrictMode. ' +
|
||||
'findNodeHandle was passed an instance of ContainsStrictModeChild which renders StrictMode children. ' +
|
||||
'Instead, add a ref directly to the element you want to reference. ' +
|
||||
@@ -1291,8 +1293,8 @@ describe('ReactFabric', () => {
|
||||
);
|
||||
});
|
||||
|
||||
let match;
|
||||
expect(() => (match = ReactFabric.findNodeHandle(parent))).toErrorDev([
|
||||
const match = ReactFabric.findNodeHandle(parent);
|
||||
assertConsoleErrorDev([
|
||||
'findNodeHandle is deprecated in StrictMode. ' +
|
||||
'findNodeHandle was passed an instance of IsInStrictMode which is inside StrictMode. ' +
|
||||
'Instead, add a ref directly to the element you want to reference. ' +
|
||||
@@ -1313,16 +1315,16 @@ describe('ReactFabric', () => {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
ReactFabric.render(<TestComponent />, 11, null, true);
|
||||
});
|
||||
}).toErrorDev([
|
||||
await act(() => {
|
||||
ReactFabric.render(<TestComponent />, 11, null, true);
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
'TestComponent is accessing findNodeHandle inside its render(). ' +
|
||||
'render() should be a pure function of props and state. It should ' +
|
||||
'never access something that requires stale data from the previous ' +
|
||||
'render, such as refs. Move this logic to componentDidMount and ' +
|
||||
'componentDidUpdate instead.',
|
||||
'componentDidUpdate instead.\n' +
|
||||
' in TestComponent (at **)',
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ let ReactNative;
|
||||
let ResponderEventPlugin;
|
||||
let UIManager;
|
||||
let createReactNativeComponentClass;
|
||||
let assertConsoleErrorDev;
|
||||
|
||||
// Parallels requireNativeComponent() in that it lazily constructs a view config,
|
||||
// And registers view manager event types with ReactNativeViewConfigRegistry.
|
||||
@@ -69,6 +70,7 @@ beforeEach(() => {
|
||||
require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface').RCTEventEmitter;
|
||||
React = require('react');
|
||||
act = require('internal-test-utils').act;
|
||||
assertConsoleErrorDev = require('internal-test-utils').assertConsoleErrorDev;
|
||||
ReactNative = require('react-native-renderer');
|
||||
ResponderEventPlugin =
|
||||
require('react-native-renderer/src/legacy-events/ResponderEventPlugin').default;
|
||||
@@ -227,30 +229,32 @@ test('handles events on text nodes', () => {
|
||||
}
|
||||
|
||||
const log = [];
|
||||
expect(() => {
|
||||
ReactNative.render(
|
||||
<ContextHack>
|
||||
<Text>
|
||||
<Text
|
||||
onTouchEnd={() => log.push('string touchend')}
|
||||
onTouchEndCapture={() => log.push('string touchend capture')}
|
||||
onTouchStart={() => log.push('string touchstart')}
|
||||
onTouchStartCapture={() => log.push('string touchstart capture')}>
|
||||
Text Content
|
||||
</Text>
|
||||
<Text
|
||||
onTouchEnd={() => log.push('number touchend')}
|
||||
onTouchEndCapture={() => log.push('number touchend capture')}
|
||||
onTouchStart={() => log.push('number touchstart')}
|
||||
onTouchStartCapture={() => log.push('number touchstart capture')}>
|
||||
{123}
|
||||
</Text>
|
||||
ReactNative.render(
|
||||
<ContextHack>
|
||||
<Text>
|
||||
<Text
|
||||
onTouchEnd={() => log.push('string touchend')}
|
||||
onTouchEndCapture={() => log.push('string touchend capture')}
|
||||
onTouchStart={() => log.push('string touchstart')}
|
||||
onTouchStartCapture={() => log.push('string touchstart capture')}>
|
||||
Text Content
|
||||
</Text>
|
||||
</ContextHack>,
|
||||
1,
|
||||
);
|
||||
}).toErrorDev([
|
||||
'ContextHack uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',
|
||||
<Text
|
||||
onTouchEnd={() => log.push('number touchend')}
|
||||
onTouchEndCapture={() => log.push('number touchend capture')}
|
||||
onTouchStart={() => log.push('number touchstart')}
|
||||
onTouchStartCapture={() => log.push('number touchstart capture')}>
|
||||
{123}
|
||||
</Text>
|
||||
</Text>
|
||||
</ContextHack>,
|
||||
1,
|
||||
);
|
||||
assertConsoleErrorDev([
|
||||
'ContextHack uses the legacy childContextTypes API which will soon be removed. ' +
|
||||
'Use React.createContext() instead. ' +
|
||||
'(https://react.dev/link/legacy-context)' +
|
||||
'\n in ContextHack (at **)',
|
||||
]);
|
||||
|
||||
expect(UIManager.createView).toHaveBeenCalledTimes(5);
|
||||
|
||||
@@ -18,6 +18,7 @@ let UIManager;
|
||||
let TextInputState;
|
||||
let ReactNativePrivateInterface;
|
||||
let act;
|
||||
let assertConsoleErrorDev;
|
||||
|
||||
const DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT =
|
||||
"dispatchCommand was called with a ref that isn't a " +
|
||||
@@ -32,7 +33,7 @@ describe('ReactNative', () => {
|
||||
jest.resetModules();
|
||||
|
||||
React = require('react');
|
||||
act = require('internal-test-utils').act;
|
||||
({act, assertConsoleErrorDev} = require('internal-test-utils'));
|
||||
StrictMode = React.StrictMode;
|
||||
ReactNative = require('react-native-renderer');
|
||||
ReactNativePrivateInterface = require('react-native/Libraries/ReactPrivate/ReactNativePrivateInterface');
|
||||
@@ -158,9 +159,8 @@ describe('ReactNative', () => {
|
||||
);
|
||||
|
||||
expect(UIManager.dispatchViewManagerCommand).not.toBeCalled();
|
||||
expect(() => {
|
||||
ReactNative.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
|
||||
}).toErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT], {
|
||||
ReactNative.dispatchCommand(viewRef, 'updateCommand', [10, 20]);
|
||||
assertConsoleErrorDev([DISPATCH_COMMAND_REQUIRES_HOST_COMPONENT], {
|
||||
withoutStack: true,
|
||||
});
|
||||
|
||||
@@ -219,9 +219,8 @@ describe('ReactNative', () => {
|
||||
);
|
||||
|
||||
expect(UIManager.sendAccessibilityEvent).not.toBeCalled();
|
||||
expect(() => {
|
||||
ReactNative.sendAccessibilityEvent(viewRef, 'updateCommand', [10, 20]);
|
||||
}).toErrorDev([SEND_ACCESSIBILITY_EVENT_REQUIRES_HOST_COMPONENT], {
|
||||
ReactNative.sendAccessibilityEvent(viewRef, 'updateCommand', [10, 20]);
|
||||
assertConsoleErrorDev([SEND_ACCESSIBILITY_EVENT_REQUIRES_HOST_COMPONENT], {
|
||||
withoutStack: true,
|
||||
});
|
||||
|
||||
@@ -614,10 +613,8 @@ describe('ReactNative', () => {
|
||||
|
||||
ReactNative.render(<ContainsStrictModeChild ref={n => (parent = n)} />, 11);
|
||||
|
||||
let match;
|
||||
expect(
|
||||
() => (match = ReactNative.findHostInstance_DEPRECATED(parent)),
|
||||
).toErrorDev([
|
||||
const match = ReactNative.findHostInstance_DEPRECATED(parent);
|
||||
assertConsoleErrorDev([
|
||||
'findHostInstance_DEPRECATED is deprecated in StrictMode. ' +
|
||||
'findHostInstance_DEPRECATED was passed an instance of ContainsStrictModeChild which renders StrictMode children. ' +
|
||||
'Instead, add a ref directly to the element you want to reference. ' +
|
||||
@@ -652,10 +649,8 @@ describe('ReactNative', () => {
|
||||
11,
|
||||
);
|
||||
|
||||
let match;
|
||||
expect(
|
||||
() => (match = ReactNative.findHostInstance_DEPRECATED(parent)),
|
||||
).toErrorDev([
|
||||
const match = ReactNative.findHostInstance_DEPRECATED(parent);
|
||||
assertConsoleErrorDev([
|
||||
'findHostInstance_DEPRECATED is deprecated in StrictMode. ' +
|
||||
'findHostInstance_DEPRECATED was passed an instance of IsInStrictMode which is inside StrictMode. ' +
|
||||
'Instead, add a ref directly to the element you want to reference. ' +
|
||||
@@ -689,8 +684,8 @@ describe('ReactNative', () => {
|
||||
|
||||
ReactNative.render(<ContainsStrictModeChild ref={n => (parent = n)} />, 11);
|
||||
|
||||
let match;
|
||||
expect(() => (match = ReactNative.findNodeHandle(parent))).toErrorDev([
|
||||
const match = ReactNative.findNodeHandle(parent);
|
||||
assertConsoleErrorDev([
|
||||
'findNodeHandle is deprecated in StrictMode. ' +
|
||||
'findNodeHandle was passed an instance of ContainsStrictModeChild which renders StrictMode children. ' +
|
||||
'Instead, add a ref directly to the element you want to reference. ' +
|
||||
@@ -725,8 +720,8 @@ describe('ReactNative', () => {
|
||||
11,
|
||||
);
|
||||
|
||||
let match;
|
||||
expect(() => (match = ReactNative.findNodeHandle(parent))).toErrorDev([
|
||||
const match = ReactNative.findNodeHandle(parent);
|
||||
assertConsoleErrorDev([
|
||||
'findNodeHandle is deprecated in StrictMode. ' +
|
||||
'findNodeHandle was passed an instance of IsInStrictMode which is inside StrictMode. ' +
|
||||
'Instead, add a ref directly to the element you want to reference. ' +
|
||||
|
||||
@@ -233,8 +233,28 @@ describe('ReactLazy', () => {
|
||||
expect(error.message).toMatch('Element type is invalid');
|
||||
assertLog(['Loading...']);
|
||||
assertConsoleErrorDev([
|
||||
'Expected the result of a dynamic import() call',
|
||||
'Expected the result of a dynamic import() call',
|
||||
'lazy: Expected the result of a dynamic import() call. ' +
|
||||
'Instead received: function Text(props) {\n' +
|
||||
' Scheduler.log(props.text);\n' +
|
||||
' return props.text;\n' +
|
||||
' }\n\n' +
|
||||
'Your code should look like: \n ' +
|
||||
"const MyComponent = lazy(() => import('./MyComponent'))\n" +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Lazy (at **)\n' + ' in Suspense (at **)\n') +
|
||||
' in App (at **)',
|
||||
'lazy: Expected the result of a dynamic import() call. ' +
|
||||
'Instead received: function Text(props) {\n' +
|
||||
' Scheduler.log(props.text);\n' +
|
||||
' return props.text;\n' +
|
||||
' }\n\n' +
|
||||
'Your code should look like: \n ' +
|
||||
"const MyComponent = lazy(() => import('./MyComponent'))\n" +
|
||||
(gate('enableOwnerStacks')
|
||||
? ''
|
||||
: ' in Lazy (at **)\n' + ' in Suspense (at **)\n') +
|
||||
' in App (at **)',
|
||||
]);
|
||||
expect(root).not.toMatchRenderedOutput('Hi');
|
||||
});
|
||||
@@ -852,19 +872,21 @@ describe('ReactLazy', () => {
|
||||
expect(root).not.toMatchRenderedOutput('22');
|
||||
|
||||
// Mount
|
||||
await expect(async () => {
|
||||
await act(() => resolveFakeImport(Add));
|
||||
}).toErrorDev(
|
||||
shouldWarnAboutFunctionDefaultProps
|
||||
? [
|
||||
'Add: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.',
|
||||
]
|
||||
: shouldWarnAboutMemoDefaultProps
|
||||
? [
|
||||
'Add: Support for defaultProps will be removed from memo components in a future major release. Use JavaScript default parameters instead.',
|
||||
]
|
||||
: [],
|
||||
);
|
||||
await act(() => resolveFakeImport(Add));
|
||||
|
||||
if (shouldWarnAboutFunctionDefaultProps) {
|
||||
assertConsoleErrorDev([
|
||||
'Add: Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.\n' +
|
||||
' in Add (at **)\n' +
|
||||
' in Suspense (at **)',
|
||||
]);
|
||||
} else if (shouldWarnAboutMemoDefaultProps) {
|
||||
assertConsoleErrorDev([
|
||||
'Add: Support for defaultProps will be removed from memo components in a future major release. Use JavaScript default parameters instead.\n' +
|
||||
' in Suspense (at **)',
|
||||
]);
|
||||
}
|
||||
|
||||
expect(root).toMatchRenderedOutput('22');
|
||||
|
||||
// Update
|
||||
|
||||
@@ -491,4 +491,46 @@ describe('ReactSuspenseyCommitPhase', () => {
|
||||
</>,
|
||||
);
|
||||
});
|
||||
|
||||
// FIXME: Should pass with `enableYieldingBeforePassive`
|
||||
// @gate !enableYieldingBeforePassive
|
||||
it('runs passive effects after suspended commit resolves', async () => {
|
||||
function Effect() {
|
||||
React.useEffect(() => {
|
||||
Scheduler.log('flush effect');
|
||||
});
|
||||
return <Text text="render effect" />;
|
||||
}
|
||||
|
||||
const root = ReactNoop.createRoot();
|
||||
|
||||
await act(() => {
|
||||
root.render(
|
||||
<Suspense fallback={<Text text="Loading..." />}>
|
||||
<Effect />
|
||||
<SuspenseyImage src="A" />
|
||||
</Suspense>,
|
||||
);
|
||||
});
|
||||
|
||||
assertLog([
|
||||
'render effect',
|
||||
'Image requested [A]',
|
||||
'Loading...',
|
||||
'render effect',
|
||||
]);
|
||||
expect(root).toMatchRenderedOutput('Loading...');
|
||||
|
||||
await act(() => {
|
||||
resolveSuspenseyThing('A');
|
||||
});
|
||||
|
||||
assertLog(['flush effect']);
|
||||
expect(root).toMatchRenderedOutput(
|
||||
<>
|
||||
{'render effect'}
|
||||
<suspensey-thing src="A" />
|
||||
</>,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,6 +9,7 @@ if (process.env.NODE_ENV === 'production') {
|
||||
|
||||
exports.renderToReadableStream = s.renderToReadableStream;
|
||||
exports.decodeReply = s.decodeReply;
|
||||
exports.decodeReplyFromAsyncIterable = s.decodeReplyFromAsyncIterable;
|
||||
exports.decodeAction = s.decodeAction;
|
||||
exports.decodeFormState = s.decodeFormState;
|
||||
exports.createClientReference = s.createClientReference;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
export {
|
||||
renderToReadableStream,
|
||||
decodeReply,
|
||||
decodeReplyFromAsyncIterable,
|
||||
decodeAction,
|
||||
decodeFormState,
|
||||
createClientReference,
|
||||
|
||||
@@ -17,6 +17,8 @@ import {
|
||||
type ServerReferenceId,
|
||||
} from '../client/ReactFlightClientConfigBundlerParcel';
|
||||
|
||||
import {ASYNC_ITERATOR} from 'shared/ReactSymbols';
|
||||
|
||||
import {
|
||||
createRequest,
|
||||
createPrerenderRequest,
|
||||
@@ -30,6 +32,9 @@ import {
|
||||
createResponse,
|
||||
close,
|
||||
getRoot,
|
||||
reportGlobalError,
|
||||
resolveField,
|
||||
resolveFile,
|
||||
} from 'react-server/src/ReactFlightReplyServer';
|
||||
|
||||
import {
|
||||
@@ -189,6 +194,50 @@ export function decodeReply<T>(
|
||||
return root;
|
||||
}
|
||||
|
||||
export function decodeReplyFromAsyncIterable<T>(
|
||||
iterable: AsyncIterable<[string, string | File]>,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
): Thenable<T> {
|
||||
const iterator: AsyncIterator<[string, string | File]> =
|
||||
iterable[ASYNC_ITERATOR]();
|
||||
|
||||
const response = createResponse(
|
||||
serverManifest,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
);
|
||||
|
||||
function progress(
|
||||
entry:
|
||||
| {done: false, +value: [string, string | File], ...}
|
||||
| {done: true, +value: void, ...},
|
||||
) {
|
||||
if (entry.done) {
|
||||
close(response);
|
||||
} else {
|
||||
const [name, value] = entry.value;
|
||||
if (typeof value === 'string') {
|
||||
resolveField(response, name, value);
|
||||
} else {
|
||||
resolveFile(response, name, value);
|
||||
}
|
||||
iterator.next().then(progress, error);
|
||||
}
|
||||
}
|
||||
function error(reason: Error) {
|
||||
reportGlobalError(response, reason);
|
||||
if (typeof (iterator: any).throw === 'function') {
|
||||
// The iterator protocol doesn't necessarily include this but a generator do.
|
||||
// $FlowFixMe should be able to pass mixed
|
||||
iterator.throw(reason).then(error, error);
|
||||
}
|
||||
}
|
||||
|
||||
iterator.next().then(progress, error);
|
||||
|
||||
return getRoot(response);
|
||||
}
|
||||
|
||||
export function decodeAction<T>(body: FormData): Promise<() => T> | null {
|
||||
return decodeActionImpl(body, serverManifest);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ export {
|
||||
renderToReadableStream,
|
||||
prerender as unstable_prerender,
|
||||
decodeReply,
|
||||
decodeReplyFromAsyncIterable,
|
||||
decodeAction,
|
||||
decodeFormState,
|
||||
createClientReference,
|
||||
|
||||
@@ -9,6 +9,7 @@ if (process.env.NODE_ENV === 'production') {
|
||||
|
||||
exports.renderToReadableStream = s.renderToReadableStream;
|
||||
exports.decodeReply = s.decodeReply;
|
||||
exports.decodeReplyFromAsyncIterable = s.decodeReplyFromAsyncIterable;
|
||||
exports.decodeAction = s.decodeAction;
|
||||
exports.decodeFormState = s.decodeFormState;
|
||||
exports.registerServerReference = s.registerServerReference;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
export {
|
||||
renderToReadableStream,
|
||||
decodeReply,
|
||||
decodeReplyFromAsyncIterable,
|
||||
decodeAction,
|
||||
decodeFormState,
|
||||
registerServerReference,
|
||||
|
||||
@@ -12,6 +12,8 @@ import type {Thenable} from 'shared/ReactTypes';
|
||||
import type {ClientManifest} from './ReactFlightServerConfigTurbopackBundler';
|
||||
import type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';
|
||||
|
||||
import {ASYNC_ITERATOR} from 'shared/ReactSymbols';
|
||||
|
||||
import {
|
||||
createRequest,
|
||||
createPrerenderRequest,
|
||||
@@ -25,6 +27,9 @@ import {
|
||||
createResponse,
|
||||
close,
|
||||
getRoot,
|
||||
reportGlobalError,
|
||||
resolveField,
|
||||
resolveFile,
|
||||
} from 'react-server/src/ReactFlightReplyServer';
|
||||
|
||||
import {
|
||||
@@ -183,10 +188,56 @@ function decodeReply<T>(
|
||||
return root;
|
||||
}
|
||||
|
||||
function decodeReplyFromAsyncIterable<T>(
|
||||
iterable: AsyncIterable<[string, string | File]>,
|
||||
turbopackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
): Thenable<T> {
|
||||
const iterator: AsyncIterator<[string, string | File]> =
|
||||
iterable[ASYNC_ITERATOR]();
|
||||
|
||||
const response = createResponse(
|
||||
turbopackMap,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
);
|
||||
|
||||
function progress(
|
||||
entry:
|
||||
| {done: false, +value: [string, string | File], ...}
|
||||
| {done: true, +value: void, ...},
|
||||
) {
|
||||
if (entry.done) {
|
||||
close(response);
|
||||
} else {
|
||||
const [name, value] = entry.value;
|
||||
if (typeof value === 'string') {
|
||||
resolveField(response, name, value);
|
||||
} else {
|
||||
resolveFile(response, name, value);
|
||||
}
|
||||
iterator.next().then(progress, error);
|
||||
}
|
||||
}
|
||||
function error(reason: Error) {
|
||||
reportGlobalError(response, reason);
|
||||
if (typeof (iterator: any).throw === 'function') {
|
||||
// The iterator protocol doesn't necessarily include this but a generator do.
|
||||
// $FlowFixMe should be able to pass mixed
|
||||
iterator.throw(reason).then(error, error);
|
||||
}
|
||||
}
|
||||
|
||||
iterator.next().then(progress, error);
|
||||
|
||||
return getRoot(response);
|
||||
}
|
||||
|
||||
export {
|
||||
renderToReadableStream,
|
||||
prerender,
|
||||
decodeReply,
|
||||
decodeReplyFromAsyncIterable,
|
||||
decodeAction,
|
||||
decodeFormState,
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ export {
|
||||
renderToReadableStream,
|
||||
prerender as unstable_prerender,
|
||||
decodeReply,
|
||||
decodeReplyFromAsyncIterable,
|
||||
decodeAction,
|
||||
decodeFormState,
|
||||
registerServerReference,
|
||||
|
||||
@@ -9,6 +9,7 @@ if (process.env.NODE_ENV === 'production') {
|
||||
|
||||
exports.renderToReadableStream = s.renderToReadableStream;
|
||||
exports.decodeReply = s.decodeReply;
|
||||
exports.decodeReplyFromAsyncIterable = s.decodeReplyFromAsyncIterable;
|
||||
exports.decodeAction = s.decodeAction;
|
||||
exports.decodeFormState = s.decodeFormState;
|
||||
exports.registerServerReference = s.registerServerReference;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
export {
|
||||
renderToReadableStream,
|
||||
decodeReply,
|
||||
decodeReplyFromAsyncIterable,
|
||||
decodeAction,
|
||||
decodeFormState,
|
||||
registerServerReference,
|
||||
|
||||
+33
-19
@@ -38,6 +38,7 @@ let ReactServerDOM;
|
||||
let Scheduler;
|
||||
let ReactServerScheduler;
|
||||
let reactServerAct;
|
||||
let assertConsoleErrorDev;
|
||||
|
||||
describe('ReactFlightDOMBrowser', () => {
|
||||
beforeEach(() => {
|
||||
@@ -75,7 +76,7 @@ describe('ReactFlightDOMBrowser', () => {
|
||||
Scheduler = require('scheduler');
|
||||
patchMessageChannel(Scheduler);
|
||||
|
||||
act = require('internal-test-utils').act;
|
||||
({act, assertConsoleErrorDev} = require('internal-test-utils'));
|
||||
React = require('react');
|
||||
ReactDOM = require('react-dom');
|
||||
ReactDOMClient = require('react-dom/client');
|
||||
@@ -1156,25 +1157,38 @@ describe('ReactFlightDOMBrowser', () => {
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
|
||||
await expect(async () => {
|
||||
const stream = await serverAct(() =>
|
||||
ReactServerDOMServer.renderToReadableStream(
|
||||
<>
|
||||
<Parent>{Array(6).fill(<div>no key</div>)}</Parent>
|
||||
<ParentModule.Parent>
|
||||
{Array(6).fill(<div>no key</div>)}
|
||||
</ParentModule.Parent>
|
||||
</>,
|
||||
webpackMap,
|
||||
),
|
||||
);
|
||||
const result =
|
||||
await ReactServerDOMClient.createFromReadableStream(stream);
|
||||
const stream = await serverAct(() =>
|
||||
ReactServerDOMServer.renderToReadableStream(
|
||||
<>
|
||||
<Parent>{Array(6).fill(<div>no key</div>)}</Parent>
|
||||
<ParentModule.Parent>
|
||||
{Array(6).fill(<div>no key</div>)}
|
||||
</ParentModule.Parent>
|
||||
</>,
|
||||
webpackMap,
|
||||
),
|
||||
);
|
||||
const result = await ReactServerDOMClient.createFromReadableStream(stream);
|
||||
|
||||
await act(() => {
|
||||
root.render(result);
|
||||
});
|
||||
}).toErrorDev('Each child in a list should have a unique "key" prop.');
|
||||
if (!gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
}
|
||||
|
||||
await act(() => {
|
||||
root.render(result);
|
||||
});
|
||||
if (gate(flags => flags.enableOwnerStacks)) {
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ParentClient>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
it('basic use(promise)', async () => {
|
||||
|
||||
+13
-8
@@ -37,6 +37,7 @@ let ReactServerDOMStaticServer;
|
||||
let ReactServerDOMClient;
|
||||
let use;
|
||||
let reactServerAct;
|
||||
let assertConsoleErrorDev;
|
||||
|
||||
function normalizeCodeLocInfo(str) {
|
||||
return (
|
||||
@@ -66,6 +67,8 @@ describe('ReactFlightDOMEdge', () => {
|
||||
jest.resetModules();
|
||||
|
||||
reactServerAct = require('internal-test-utils').serverAct;
|
||||
assertConsoleErrorDev =
|
||||
require('internal-test-utils').assertConsoleErrorDev;
|
||||
|
||||
// Simulate the condition resolution
|
||||
jest.mock('react', () => require('react/react.react-server'));
|
||||
@@ -802,17 +805,19 @@ describe('ReactFlightDOMEdge', () => {
|
||||
),
|
||||
};
|
||||
|
||||
expect(() => {
|
||||
ServerModule.greet.bind({}, 'hi');
|
||||
}).toErrorDev(
|
||||
'Cannot bind "this" of a Server Action. Pass null or undefined as the first argument to .bind().',
|
||||
ServerModule.greet.bind({}, 'hi');
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Cannot bind "this" of a Server Action. Pass null or undefined as the first argument to .bind().',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
ServerModuleImportedOnClient.greet.bind({}, 'hi');
|
||||
}).toErrorDev(
|
||||
'Cannot bind "this" of a Server Action. Pass null or undefined as the first argument to .bind().',
|
||||
ServerModuleImportedOnClient.greet.bind({}, 'hi');
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'Cannot bind "this" of a Server Action. Pass null or undefined as the first argument to .bind().',
|
||||
],
|
||||
{withoutStack: true},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -50,6 +50,7 @@ let ReactServerDOMClient;
|
||||
let ReactDOMClient;
|
||||
let useActionState;
|
||||
let act;
|
||||
let assertConsoleErrorDev;
|
||||
|
||||
describe('ReactFlightDOMForm', () => {
|
||||
beforeEach(() => {
|
||||
@@ -72,6 +73,8 @@ describe('ReactFlightDOMForm', () => {
|
||||
ReactDOMServer = require('react-dom/server.edge');
|
||||
ReactDOMClient = require('react-dom/client');
|
||||
act = React.act;
|
||||
assertConsoleErrorDev =
|
||||
require('internal-test-utils').assertConsoleErrorDev;
|
||||
|
||||
// TODO: Test the old api but it warns so needs warnings to be asserted.
|
||||
// if (__VARIANT__) {
|
||||
@@ -959,12 +962,13 @@ describe('ReactFlightDOMForm', () => {
|
||||
await readIntoContainer(postbackSsrStream);
|
||||
}
|
||||
|
||||
await expect(submitTheForm).toErrorDev(
|
||||
await submitTheForm();
|
||||
assertConsoleErrorDev([
|
||||
'Failed to serialize an action for progressive enhancement:\n' +
|
||||
'Error: React Element cannot be passed to Server Functions from the Client without a temporary reference set. Pass a TemporaryReferenceSet to the options.\n' +
|
||||
' [<div/>]\n' +
|
||||
' ^^^^^^',
|
||||
);
|
||||
]);
|
||||
|
||||
// The error message was returned as JSX.
|
||||
const form2 = container.getElementsByTagName('form')[0];
|
||||
@@ -1035,10 +1039,11 @@ describe('ReactFlightDOMForm', () => {
|
||||
await readIntoContainer(postbackSsrStream);
|
||||
}
|
||||
|
||||
await expect(submitTheForm).toErrorDev(
|
||||
await submitTheForm();
|
||||
assertConsoleErrorDev([
|
||||
'Failed to serialize an action for progressive enhancement:\n' +
|
||||
'Error: File/Blob fields are not yet supported in progressive forms. Will fallback to client hydration.',
|
||||
);
|
||||
]);
|
||||
|
||||
expect(blob instanceof Blob).toBe(true);
|
||||
expect(blob.size).toBe(2);
|
||||
|
||||
+36
@@ -272,4 +272,40 @@ describe('ReactFlightDOMReplyEdge', () => {
|
||||
expect(error).not.toBe(null);
|
||||
expect(error.message).toBe('Connection closed.');
|
||||
});
|
||||
|
||||
it('can stream the decoding using an async iterable', async () => {
|
||||
let resolve;
|
||||
const promise = new Promise(r => (resolve = r));
|
||||
|
||||
const buffer = new Uint8Array([
|
||||
123, 4, 10, 5, 100, 255, 244, 45, 56, 67, 43, 124, 67, 89, 100, 20,
|
||||
]);
|
||||
|
||||
const formData = await ReactServerDOMClient.encodeReply({
|
||||
a: Promise.resolve('hello'),
|
||||
b: Promise.resolve(buffer),
|
||||
});
|
||||
|
||||
const iterable = {
|
||||
async *[Symbol.asyncIterator]() {
|
||||
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||||
for (const entry of formData) {
|
||||
yield entry;
|
||||
await promise;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const decoded = await ReactServerDOMServer.decodeReplyFromAsyncIterable(
|
||||
iterable,
|
||||
webpackServerMap,
|
||||
);
|
||||
|
||||
expect(Object.keys(decoded)).toEqual(['a', 'b']);
|
||||
|
||||
await resolve();
|
||||
|
||||
expect(await decoded.a).toBe('hello');
|
||||
expect(Array.from(await decoded.b)).toEqual(Array.from(buffer));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -12,6 +12,8 @@ import type {Thenable} from 'shared/ReactTypes';
|
||||
import type {ClientManifest} from './ReactFlightServerConfigWebpackBundler';
|
||||
import type {ServerManifest} from 'react-client/src/ReactFlightClientConfig';
|
||||
|
||||
import {ASYNC_ITERATOR} from 'shared/ReactSymbols';
|
||||
|
||||
import {
|
||||
createRequest,
|
||||
createPrerenderRequest,
|
||||
@@ -25,6 +27,9 @@ import {
|
||||
createResponse,
|
||||
close,
|
||||
getRoot,
|
||||
reportGlobalError,
|
||||
resolveField,
|
||||
resolveFile,
|
||||
} from 'react-server/src/ReactFlightReplyServer';
|
||||
|
||||
import {
|
||||
@@ -183,10 +188,56 @@ function decodeReply<T>(
|
||||
return root;
|
||||
}
|
||||
|
||||
function decodeReplyFromAsyncIterable<T>(
|
||||
iterable: AsyncIterable<[string, string | File]>,
|
||||
webpackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
): Thenable<T> {
|
||||
const iterator: AsyncIterator<[string, string | File]> =
|
||||
iterable[ASYNC_ITERATOR]();
|
||||
|
||||
const response = createResponse(
|
||||
webpackMap,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
);
|
||||
|
||||
function progress(
|
||||
entry:
|
||||
| {done: false, +value: [string, string | File], ...}
|
||||
| {done: true, +value: void, ...},
|
||||
) {
|
||||
if (entry.done) {
|
||||
close(response);
|
||||
} else {
|
||||
const [name, value] = entry.value;
|
||||
if (typeof value === 'string') {
|
||||
resolveField(response, name, value);
|
||||
} else {
|
||||
resolveFile(response, name, value);
|
||||
}
|
||||
iterator.next().then(progress, error);
|
||||
}
|
||||
}
|
||||
function error(reason: Error) {
|
||||
reportGlobalError(response, reason);
|
||||
if (typeof (iterator: any).throw === 'function') {
|
||||
// The iterator protocol doesn't necessarily include this but a generator do.
|
||||
// $FlowFixMe should be able to pass mixed
|
||||
iterator.throw(reason).then(error, error);
|
||||
}
|
||||
}
|
||||
|
||||
iterator.next().then(progress, error);
|
||||
|
||||
return getRoot(response);
|
||||
}
|
||||
|
||||
export {
|
||||
renderToReadableStream,
|
||||
prerender,
|
||||
decodeReply,
|
||||
decodeReplyFromAsyncIterable,
|
||||
decodeAction,
|
||||
decodeFormState,
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ export {
|
||||
renderToReadableStream,
|
||||
prerender as unstable_prerender,
|
||||
decodeReply,
|
||||
decodeReplyFromAsyncIterable,
|
||||
decodeAction,
|
||||
decodeFormState,
|
||||
registerServerReference,
|
||||
|
||||
@@ -14,6 +14,7 @@ let React;
|
||||
let ReactCache;
|
||||
let ReactTestRenderer;
|
||||
let act;
|
||||
let assertConsoleErrorDev;
|
||||
|
||||
describe('ReactTestRenderer', () => {
|
||||
beforeEach(() => {
|
||||
@@ -27,19 +28,27 @@ describe('ReactTestRenderer', () => {
|
||||
ReactTestRenderer = require('react-test-renderer');
|
||||
const InternalTestUtils = require('internal-test-utils');
|
||||
act = InternalTestUtils.act;
|
||||
assertConsoleErrorDev = InternalTestUtils.assertConsoleErrorDev;
|
||||
});
|
||||
|
||||
it('should warn if used to render a ReactDOM portal', async () => {
|
||||
const container = document.createElement('div');
|
||||
let error;
|
||||
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
ReactTestRenderer.create(ReactDOM.createPortal('foo', container));
|
||||
}).catch(e => (error = e));
|
||||
}).toErrorDev('An invalid container has been provided.', {
|
||||
withoutStack: true,
|
||||
});
|
||||
await act(() => {
|
||||
ReactTestRenderer.create(ReactDOM.createPortal('foo', container));
|
||||
}).catch(e => (error = e));
|
||||
assertConsoleErrorDev(
|
||||
[
|
||||
'An invalid container has been provided. ' +
|
||||
'This may indicate that another renderer is being used in addition to the test renderer. ' +
|
||||
'(For example, ReactDOM.createPortal inside of a ReactTestRenderer tree.) ' +
|
||||
'This is not supported.',
|
||||
],
|
||||
{
|
||||
withoutStack: true,
|
||||
},
|
||||
);
|
||||
|
||||
// After the update throws, a subsequent render is scheduled to
|
||||
// unmount the whole tree. This update also causes an error, so React
|
||||
|
||||
@@ -13,12 +13,13 @@ describe('ReactChildren', () => {
|
||||
let React;
|
||||
let ReactDOMClient;
|
||||
let act;
|
||||
let assertConsoleErrorDev;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
React = require('react');
|
||||
ReactDOMClient = require('react-dom/client');
|
||||
act = require('internal-test-utils').act;
|
||||
({act, assertConsoleErrorDev} = require('internal-test-utils'));
|
||||
});
|
||||
|
||||
it('should support identity for simple', () => {
|
||||
@@ -331,14 +332,16 @@ describe('ReactChildren', () => {
|
||||
callback.mockClear();
|
||||
}
|
||||
|
||||
let instance;
|
||||
expect(() => {
|
||||
instance = <div>{threeDivIterable}</div>;
|
||||
}).toErrorDev(
|
||||
const instance = <div>{threeDivIterable}</div>;
|
||||
assertConsoleErrorDev(
|
||||
// With the flag on this doesn't warn eagerly but only when rendered
|
||||
gate(flag => flag.enableOwnerStacks)
|
||||
? []
|
||||
: ['Each child in a list should have a unique "key" prop.'],
|
||||
: [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <div>. See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
],
|
||||
);
|
||||
|
||||
React.Children.forEach(instance.props.children, callback, context);
|
||||
@@ -359,11 +362,16 @@ describe('ReactChildren', () => {
|
||||
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render(instance);
|
||||
});
|
||||
}).toErrorDev('Each child in a list should have a unique "key" prop.');
|
||||
await act(() => {
|
||||
root.render(instance);
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <div>. It was passed a child from div.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)' +
|
||||
(gate(flag => flag.enableOwnerStacks) ? '' : '\n in div (at **)'),
|
||||
]);
|
||||
});
|
||||
|
||||
it('should be called for each child in an iterable with keys', () => {
|
||||
@@ -879,15 +887,29 @@ describe('ReactChildren', () => {
|
||||
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render(
|
||||
<ComponentRenderingMappedChildren>
|
||||
{[<div />]}
|
||||
</ComponentRenderingMappedChildren>,
|
||||
);
|
||||
});
|
||||
}).toErrorDev(['Each child in a list should have a unique "key" prop.']);
|
||||
await act(() => {
|
||||
root.render(
|
||||
<ComponentRenderingMappedChildren>
|
||||
{[<div />]}
|
||||
</ComponentRenderingMappedChildren>,
|
||||
);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentRenderingMappedChildren`.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)\n' +
|
||||
' in **/ReactChildren-test.js:**:** (at **)',
|
||||
]
|
||||
: [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ComponentRenderingMappedChildren>.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
it('does not warn for mapped static children without keys', async () => {
|
||||
@@ -903,16 +925,14 @@ describe('ReactChildren', () => {
|
||||
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render(
|
||||
<ComponentRenderingMappedChildren>
|
||||
<div />
|
||||
<div />
|
||||
</ComponentRenderingMappedChildren>,
|
||||
);
|
||||
});
|
||||
}).toErrorDev([]);
|
||||
await act(() => {
|
||||
root.render(
|
||||
<ComponentRenderingMappedChildren>
|
||||
<div />
|
||||
<div />
|
||||
</ComponentRenderingMappedChildren>,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('warns for cloned list children without keys', async () => {
|
||||
@@ -926,15 +946,28 @@ describe('ReactChildren', () => {
|
||||
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render(
|
||||
<ComponentRenderingClonedChildren>
|
||||
{[<div />]}
|
||||
</ComponentRenderingClonedChildren>,
|
||||
);
|
||||
});
|
||||
}).toErrorDev(['Each child in a list should have a unique "key" prop.']);
|
||||
await act(() => {
|
||||
root.render(
|
||||
<ComponentRenderingClonedChildren>
|
||||
{[<div />]}
|
||||
</ComponentRenderingClonedChildren>,
|
||||
);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentRenderingClonedChildren`.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]
|
||||
: [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ComponentRenderingClonedChildren>.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
it('does not warn for cloned static children without keys', async () => {
|
||||
@@ -948,16 +981,14 @@ describe('ReactChildren', () => {
|
||||
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render(
|
||||
<ComponentRenderingClonedChildren>
|
||||
<div />
|
||||
<div />
|
||||
</ComponentRenderingClonedChildren>,
|
||||
);
|
||||
});
|
||||
}).toErrorDev([]);
|
||||
await act(() => {
|
||||
root.render(
|
||||
<ComponentRenderingClonedChildren>
|
||||
<div />
|
||||
<div />
|
||||
</ComponentRenderingClonedChildren>,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('warns for flattened list children without keys', async () => {
|
||||
@@ -967,15 +998,28 @@ describe('ReactChildren', () => {
|
||||
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render(
|
||||
<ComponentRenderingFlattenedChildren>
|
||||
{[<div />]}
|
||||
</ComponentRenderingFlattenedChildren>,
|
||||
);
|
||||
});
|
||||
}).toErrorDev(['Each child in a list should have a unique "key" prop.']);
|
||||
await act(() => {
|
||||
root.render(
|
||||
<ComponentRenderingFlattenedChildren>
|
||||
{[<div />]}
|
||||
</ComponentRenderingFlattenedChildren>,
|
||||
);
|
||||
});
|
||||
assertConsoleErrorDev(
|
||||
gate(flags => flags.enableOwnerStacks)
|
||||
? [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the render method of `ComponentRenderingFlattenedChildren`.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
]
|
||||
: [
|
||||
'Each child in a list should have a unique "key" prop.\n\n' +
|
||||
'Check the top-level render call using <ComponentRenderingFlattenedChildren>.' +
|
||||
' See https://react.dev/link/warning-keys for more information.\n' +
|
||||
' in div (at **)',
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
it('does not warn for flattened static children without keys', async () => {
|
||||
@@ -985,16 +1029,14 @@ describe('ReactChildren', () => {
|
||||
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render(
|
||||
<ComponentRenderingFlattenedChildren>
|
||||
<div />
|
||||
<div />
|
||||
</ComponentRenderingFlattenedChildren>,
|
||||
);
|
||||
});
|
||||
}).toErrorDev([]);
|
||||
await act(() => {
|
||||
root.render(
|
||||
<ComponentRenderingFlattenedChildren>
|
||||
<div />
|
||||
<div />
|
||||
</ComponentRenderingFlattenedChildren>,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should escape keys', () => {
|
||||
@@ -1153,18 +1195,16 @@ describe('ReactChildren', () => {
|
||||
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render(<ComponentReturningArray />);
|
||||
});
|
||||
}).toErrorDev(
|
||||
'' +
|
||||
'Each child in a list should have a unique "key" prop.' +
|
||||
await act(() => {
|
||||
root.render(<ComponentReturningArray />);
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.' +
|
||||
'\n\nCheck the top-level render call using <ComponentReturningArray>. It was passed a child from ComponentReturningArray. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.' +
|
||||
'\n in div (at **)' +
|
||||
'\n in ComponentReturningArray (at **)',
|
||||
);
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not warn when there are keys on elements in a fragment', async () => {
|
||||
@@ -1184,17 +1224,15 @@ describe('ReactChildren', () => {
|
||||
it('warns for keys for arrays at the top level', async () => {
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await expect(async () => {
|
||||
await act(() => {
|
||||
root.render([<div />, <div />]);
|
||||
});
|
||||
}).toErrorDev(
|
||||
'' +
|
||||
'Each child in a list should have a unique "key" prop.' +
|
||||
await act(() => {
|
||||
root.render([<div />, <div />]);
|
||||
});
|
||||
assertConsoleErrorDev([
|
||||
'Each child in a list should have a unique "key" prop.' +
|
||||
'\n\nCheck the top-level render call using <Root>. ' +
|
||||
'See https://react.dev/link/warning-keys for more information.' +
|
||||
'\n in div (at **)',
|
||||
);
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,6 +9,8 @@ PropTypes = null
|
||||
React = null
|
||||
ReactDOM = null
|
||||
ReactDOMClient = null
|
||||
assertConsoleErrorDev = null
|
||||
assertConsoleWarnDev = null
|
||||
|
||||
featureFlags = require 'shared/ReactFeatureFlags'
|
||||
|
||||
@@ -28,6 +30,9 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
root = ReactDOMClient.createRoot container
|
||||
attachedListener = null
|
||||
renderedName = null
|
||||
TestUtils = require 'internal-test-utils'
|
||||
assertConsoleErrorDev = TestUtils.assertConsoleErrorDev
|
||||
assertConsoleWarnDev = TestUtils.assertConsoleWarnDev
|
||||
InnerComponent = class extends React.Component
|
||||
getName: -> this.props.name
|
||||
render: ->
|
||||
@@ -53,14 +58,15 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
event.preventDefault()
|
||||
caughtErrors.push(event.error)
|
||||
window.addEventListener 'error', errorHandler;
|
||||
expect(->
|
||||
ReactDOM.flushSync ->
|
||||
root.render React.createElement(Foo)
|
||||
).toErrorDev([
|
||||
# A failed component renders twice in DEV in concurrent mode
|
||||
'No `render` method found on the Foo instance',
|
||||
'No `render` method found on the Foo instance',
|
||||
])
|
||||
ReactDOM.flushSync ->
|
||||
root.render React.createElement(Foo)
|
||||
assertConsoleErrorDev [
|
||||
# A failed component renders twice in DEV in concurrent mode
|
||||
'No `render` method found on the Foo instance: you may have forgotten to define `render`.\n' +
|
||||
' in Foo (at **)',
|
||||
'No `render` method found on the Foo instance: you may have forgotten to define `render`.\n' +
|
||||
' in Foo (at **)',
|
||||
]
|
||||
window.removeEventListener 'error', errorHandler;
|
||||
expect(caughtErrors).toEqual([
|
||||
expect.objectContaining(
|
||||
@@ -136,11 +142,11 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
React.createElement('div')
|
||||
getDerivedStateFromProps: ->
|
||||
{}
|
||||
expect(->
|
||||
ReactDOM.flushSync ->
|
||||
root.render React.createElement(Foo, foo: 'foo')
|
||||
return
|
||||
).toErrorDev 'Foo: getDerivedStateFromProps() is defined as an instance method and will be ignored. Instead, declare it as a static method.'
|
||||
ReactDOM.flushSync ->
|
||||
root.render React.createElement(Foo, foo: 'foo')
|
||||
assertConsoleErrorDev [
|
||||
'Foo: getDerivedStateFromProps() is defined as an instance method and will be ignored. Instead, declare it as a static method.\n' +
|
||||
' in Foo (at **)']
|
||||
|
||||
it 'warns if getDerivedStateFromError is not static', ->
|
||||
class Foo extends React.Component
|
||||
@@ -148,11 +154,13 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
React.createElement('div')
|
||||
getDerivedStateFromError: ->
|
||||
{}
|
||||
expect(->
|
||||
ReactDOM.flushSync ->
|
||||
root.render React.createElement(Foo, foo: 'foo')
|
||||
return
|
||||
).toErrorDev 'Foo: getDerivedStateFromError() is defined as an instance method and will be ignored. Instead, declare it as a static method.'
|
||||
ReactDOM.flushSync ->
|
||||
root.render React.createElement(Foo, foo: 'foo')
|
||||
|
||||
assertConsoleErrorDev [
|
||||
'Foo: getDerivedStateFromError() is defined as an instance method and will be ignored. Instead, declare it as a static method.\n' +
|
||||
' in Foo (at **)'
|
||||
]
|
||||
|
||||
it 'warns if getSnapshotBeforeUpdate is static', ->
|
||||
class Foo extends React.Component
|
||||
@@ -160,11 +168,13 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
React.createElement('div')
|
||||
Foo.getSnapshotBeforeUpdate = () ->
|
||||
{}
|
||||
expect(->
|
||||
ReactDOM.flushSync ->
|
||||
root.render React.createElement(Foo, foo: 'foo')
|
||||
return
|
||||
).toErrorDev 'Foo: getSnapshotBeforeUpdate() is defined as a static method and will be ignored. Instead, declare it as an instance method.'
|
||||
ReactDOM.flushSync ->
|
||||
root.render React.createElement(Foo, foo: 'foo')
|
||||
|
||||
assertConsoleErrorDev [
|
||||
'Foo: getSnapshotBeforeUpdate() is defined as a static method and will be ignored. Instead, declare it as an instance method.\n' +
|
||||
' in Foo (at **)'
|
||||
]
|
||||
|
||||
it 'warns if state not initialized before static getDerivedStateFromProps', ->
|
||||
class Foo extends React.Component
|
||||
@@ -177,16 +187,16 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
foo: nextProps.foo
|
||||
bar: 'bar'
|
||||
}
|
||||
expect(->
|
||||
ReactDOM.flushSync ->
|
||||
root.render React.createElement(Foo, foo: 'foo')
|
||||
return
|
||||
).toErrorDev (
|
||||
'`Foo` uses `getDerivedStateFromProps` but its initial state is ' +
|
||||
'undefined. This is not recommended. Instead, define the initial state by ' +
|
||||
'assigning an object to `this.state` in the constructor of `Foo`. ' +
|
||||
'This ensures that `getDerivedStateFromProps` arguments have a consistent shape.'
|
||||
)
|
||||
ReactDOM.flushSync ->
|
||||
root.render React.createElement(Foo, foo: 'foo')
|
||||
|
||||
assertConsoleErrorDev [
|
||||
'`Foo` uses `getDerivedStateFromProps` but its initial state is
|
||||
undefined. This is not recommended. Instead, define the initial state by
|
||||
assigning an object to `this.state` in the constructor of `Foo`.
|
||||
This ensures that `getDerivedStateFromProps` arguments have a consistent shape.\n' +
|
||||
' in Foo (at **)'
|
||||
]
|
||||
|
||||
it 'updates initial state with values returned by static getDerivedStateFromProps', ->
|
||||
class Foo extends React.Component
|
||||
@@ -254,12 +264,28 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
render: ->
|
||||
React.createElement Foo
|
||||
|
||||
expect(->
|
||||
test React.createElement(Outer), 'SPAN', 'foo'
|
||||
).toErrorDev([
|
||||
'Outer uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',
|
||||
'Foo uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.',
|
||||
])
|
||||
test React.createElement(Outer), 'SPAN', 'foo'
|
||||
|
||||
if featureFlags.enableOwnerStacks
|
||||
assertConsoleErrorDev([
|
||||
'Outer uses the legacy childContextTypes API which will soon be removed.
|
||||
Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Outer (at **)',
|
||||
'Foo uses the legacy contextTypes API which will soon be removed.
|
||||
Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Outer (at **)',
|
||||
]);
|
||||
else
|
||||
assertConsoleErrorDev([
|
||||
'Outer uses the legacy childContextTypes API which will soon be removed.
|
||||
Use React.createContext() instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Outer (at **)',
|
||||
'Foo uses the legacy contextTypes API which will soon be removed.
|
||||
Use React.createContext() with static contextType instead. (https://react.dev/link/legacy-context)\n' +
|
||||
' in Foo (at **)\n' +
|
||||
' in Outer (at **)',
|
||||
]);
|
||||
|
||||
|
||||
it 'renders only once when setting state in componentWillMount', ->
|
||||
renderCount = 0
|
||||
@@ -286,9 +312,11 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
render: ->
|
||||
React.createElement('span')
|
||||
|
||||
expect(->
|
||||
test React.createElement(Foo), 'SPAN', ''
|
||||
).toErrorDev('Foo.state: must be set to an object or null')
|
||||
test React.createElement(Foo), 'SPAN', ''
|
||||
assertConsoleErrorDev [
|
||||
'Foo.state: must be set to an object or null\n' +
|
||||
' in Foo (at **)'
|
||||
]
|
||||
|
||||
it 'should render with null in the initial state property', ->
|
||||
class Foo extends React.Component
|
||||
@@ -430,14 +458,21 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
className: 'foo'
|
||||
)
|
||||
|
||||
expect(->
|
||||
test React.createElement(Foo), 'SPAN', 'foo'
|
||||
).toErrorDev([
|
||||
'getInitialState was defined on Foo, a plain JavaScript class.',
|
||||
'getDefaultProps was defined on Foo, a plain JavaScript class.',
|
||||
'contextTypes was defined as an instance property on Foo.',
|
||||
'contextType was defined as an instance property on Foo.',
|
||||
])
|
||||
test React.createElement(Foo), 'SPAN', 'foo'
|
||||
assertConsoleErrorDev [
|
||||
'getInitialState was defined on Foo, a plain JavaScript class.
|
||||
This is only supported for classes created using React.createClass.
|
||||
Did you mean to define a state property instead?\n' +
|
||||
' in Foo (at **)',
|
||||
'getDefaultProps was defined on Foo, a plain JavaScript class.
|
||||
This is only supported for classes created using React.createClass.
|
||||
Use a static property to define defaultProps instead.\n' +
|
||||
' in Foo (at **)',
|
||||
'contextType was defined as an instance property on Foo. Use a static property to define contextType instead.\n' +
|
||||
' in Foo (at **)',
|
||||
'contextTypes was defined as an instance property on Foo. Use a static property to define contextTypes instead.\n' +
|
||||
' in Foo (at **)',
|
||||
]
|
||||
expect(getInitialStateWasCalled).toBe false
|
||||
expect(getDefaultPropsWasCalled).toBe false
|
||||
|
||||
@@ -468,13 +503,13 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
className: 'foo'
|
||||
)
|
||||
|
||||
expect(->
|
||||
test React.createElement(NamedComponent), 'SPAN', 'foo'
|
||||
).toErrorDev(
|
||||
test React.createElement(NamedComponent), 'SPAN', 'foo'
|
||||
assertConsoleErrorDev [
|
||||
'NamedComponent has a method called componentShouldUpdate().
|
||||
Did you mean shouldComponentUpdate()? The name is phrased as a
|
||||
question because the function is expected to return a value.'
|
||||
)
|
||||
question because the function is expected to return a value.\n' +
|
||||
' in NamedComponent (at **)'
|
||||
]
|
||||
|
||||
it 'should warn when misspelling componentWillReceiveProps', ->
|
||||
class NamedComponent extends React.Component
|
||||
@@ -486,12 +521,12 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
className: 'foo'
|
||||
)
|
||||
|
||||
expect(->
|
||||
test React.createElement(NamedComponent), 'SPAN', 'foo'
|
||||
).toErrorDev(
|
||||
test React.createElement(NamedComponent), 'SPAN', 'foo'
|
||||
assertConsoleErrorDev [
|
||||
'NamedComponent has a method called componentWillRecieveProps().
|
||||
Did you mean componentWillReceiveProps()?'
|
||||
)
|
||||
Did you mean componentWillReceiveProps()?\n' +
|
||||
' in NamedComponent (at **)'
|
||||
]
|
||||
|
||||
it 'should warn when misspelling UNSAFE_componentWillReceiveProps', ->
|
||||
class NamedComponent extends React.Component
|
||||
@@ -503,28 +538,28 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
className: 'foo'
|
||||
)
|
||||
|
||||
expect(->
|
||||
test React.createElement(NamedComponent), 'SPAN', 'foo'
|
||||
).toErrorDev(
|
||||
test React.createElement(NamedComponent), 'SPAN', 'foo'
|
||||
assertConsoleErrorDev [
|
||||
'NamedComponent has a method called UNSAFE_componentWillRecieveProps().
|
||||
Did you mean UNSAFE_componentWillReceiveProps()?'
|
||||
)
|
||||
Did you mean UNSAFE_componentWillReceiveProps()?\n' +
|
||||
' in NamedComponent (at **)'
|
||||
]
|
||||
|
||||
it 'should throw AND warn when trying to access classic APIs', ->
|
||||
ref = React.createRef()
|
||||
test React.createElement(InnerComponent, name: 'foo', ref: ref), 'DIV', 'foo'
|
||||
expect(->
|
||||
expect(-> ref.current.replaceState {}).toThrow()
|
||||
).toWarnDev(
|
||||
'replaceState(...) is deprecated in plain JavaScript React classes',
|
||||
{withoutStack: true}
|
||||
)
|
||||
expect(->
|
||||
expect(-> ref.current.isMounted()).toThrow()
|
||||
).toWarnDev(
|
||||
'isMounted(...) is deprecated in plain JavaScript React classes',
|
||||
{withoutStack: true}
|
||||
)
|
||||
|
||||
expect(-> ref.current.replaceState {}).toThrow()
|
||||
assertConsoleWarnDev([
|
||||
'replaceState(...) is deprecated in plain JavaScript React classes.
|
||||
Refactor your code to use setState instead (see https://github.com/facebook/react/issues/3236).'
|
||||
], {withoutStack: true})
|
||||
|
||||
expect(-> ref.current.isMounted()).toThrow()
|
||||
assertConsoleWarnDev([
|
||||
'isMounted(...) is deprecated in plain JavaScript React classes.
|
||||
Instead, make sure to clean up subscriptions and pending requests in componentWillUnmount to prevent memory leaks.',
|
||||
], {withoutStack: true})
|
||||
|
||||
if !featureFlags.disableLegacyContext
|
||||
it 'supports this.context passed via getChildContext', ->
|
||||
@@ -542,13 +577,25 @@ describe 'ReactCoffeeScriptClass', ->
|
||||
render: ->
|
||||
React.createElement Bar
|
||||
|
||||
expect(->
|
||||
test React.createElement(Foo), 'DIV', 'bar-through-context'
|
||||
).toErrorDev(
|
||||
[
|
||||
'Foo uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.',
|
||||
'Bar uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.',
|
||||
],
|
||||
)
|
||||
test React.createElement(Foo), 'DIV', 'bar-through-context'
|
||||
if featureFlags.enableOwnerStacks
|
||||
assertConsoleErrorDev [
|
||||
'Foo uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.
|
||||
(https://react.dev/link/legacy-context)\n' +
|
||||
' in Foo (at **)',
|
||||
'Bar uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.
|
||||
(https://react.dev/link/legacy-context)\n' +
|
||||
' in Foo (at **)'
|
||||
]
|
||||
else
|
||||
assertConsoleErrorDev [
|
||||
'Foo uses the legacy childContextTypes API which will soon be removed. Use React.createContext() instead.
|
||||
(https://react.dev/link/legacy-context)\n' +
|
||||
' in Foo (at **)',
|
||||
'Bar uses the legacy contextTypes API which will soon be removed. Use React.createContext() with static contextType instead.
|
||||
(https://react.dev/link/legacy-context)\n' +
|
||||
' in Bar (at **)\n' +
|
||||
' in Foo (at **)'
|
||||
]
|
||||
|
||||
undefined
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user