Compare commits
7 Commits
pr33071
...
multi-form
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48c5c131c6 | ||
|
|
fbdd204466 | ||
|
|
bf777c4b99 | ||
|
|
58a09a3206 | ||
|
|
c4b0701ec7 | ||
|
|
88b9767404 | ||
|
|
0038c501a3 |
@@ -48,7 +48,7 @@ import {printIdentifier, printPlace} from '../HIR/PrintHIR';
|
||||
import {eachPatternOperand} from '../HIR/visitors';
|
||||
import {Err, Ok, Result} from '../Utils/Result';
|
||||
import {GuardKind} from '../Utils/RuntimeDiagnosticConstants';
|
||||
import {assertExhaustive, hasOwnProperty} from '../Utils/utils';
|
||||
import {assertExhaustive} from '../Utils/utils';
|
||||
import {buildReactiveFunction} from './BuildReactiveFunction';
|
||||
import {SINGLE_CHILD_FBT_TAGS} from './MemoizeFbtAndMacroOperandsInSameScope';
|
||||
import {ReactiveFunctionVisitor, visitReactiveFunction} from './visitors';
|
||||
@@ -374,8 +374,6 @@ function codegenReactiveFunction(
|
||||
const countMemoBlockVisitor = new CountMemoBlockVisitor(fn.env);
|
||||
visitReactiveFunction(fn, countMemoBlockVisitor, undefined);
|
||||
|
||||
setMissingLocationsToNull(body);
|
||||
|
||||
return Ok({
|
||||
type: 'CodegenFunction',
|
||||
loc: fn.loc,
|
||||
@@ -2667,38 +2665,3 @@ function compareScopeDeclaration(
|
||||
else if (aName > bName) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
function setMissingLocationsToNull(ast: any): void {
|
||||
if (Array.isArray(ast)) {
|
||||
ast.forEach(item => setMissingLocationsToNull(item));
|
||||
return;
|
||||
} else if (
|
||||
ast == null ||
|
||||
typeof ast !== 'object' ||
|
||||
typeof ast['type'] !== 'string'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (ast['loc'] == null) {
|
||||
ast['loc'] = {
|
||||
start: {line: null, column: null, index: null},
|
||||
end: {line: null, column: null, index: null},
|
||||
filename: null,
|
||||
identifierName: null,
|
||||
};
|
||||
}
|
||||
for (const key in ast) {
|
||||
if (!hasOwnProperty(ast, key)) {
|
||||
continue;
|
||||
}
|
||||
const value = ast[key];
|
||||
if (typeof value !== 'object') {
|
||||
/*
|
||||
* We handle this above too, but avoid extra function calls in the majority of
|
||||
* cases where we're traversing an AST node's properties
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
setMissingLocationsToNull(ast[key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @sourceMaps
|
||||
export const Button = () => {
|
||||
return <button>Click me</button>;
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react/compiler-runtime"; // @sourceMaps
|
||||
export const Button = () => {
|
||||
const $ = _c(1);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = <button>Click me</button>;
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
return t0;
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Source Map
|
||||
|
||||
```
|
||||
{
|
||||
"version": 3,
|
||||
"names": [
|
||||
"Button",
|
||||
"t0"
|
||||
],
|
||||
"sources": [
|
||||
"sourcemaps-simple.ts"
|
||||
],
|
||||
"sourcesContent": [
|
||||
"// @sourceMaps\nexport const Button = () => {\n return <button>Click me</button>;\n};\n"
|
||||
],
|
||||
"mappings": "kDAAA;AACA,OAAO,MAAMA,MAAM,GAAGA,CAAA,K;SACb,OAAyB,CAAjB,QAAQ,EAAhB,MAAyB,C,qCAAzBC,EAAyB,C,CACjC",
|
||||
"ignoreList": []
|
||||
}
|
||||
```
|
||||
|
||||
### Eval output
|
||||
(kind: exception) Fixture not implemented
|
||||
@@ -1,4 +0,0 @@
|
||||
// @sourceMaps
|
||||
export const Button = () => {
|
||||
return <button>Click me</button>;
|
||||
};
|
||||
@@ -306,7 +306,6 @@ export type TransformResult = {
|
||||
original: string;
|
||||
forget: string;
|
||||
} | null;
|
||||
sourceMap: BabelCore.BabelFileResult['map'];
|
||||
};
|
||||
|
||||
export async function transformFixtureInput(
|
||||
@@ -332,9 +331,6 @@ export async function transformFixtureInput(
|
||||
// with `cwd`, which is different across machines
|
||||
const virtualFilepath = '/' + filename;
|
||||
|
||||
// Check if we should emit source maps in the test fixture
|
||||
const includeSourceMaps = firstLine.includes('@sourceMaps');
|
||||
|
||||
const presets =
|
||||
language === 'typescript'
|
||||
? TypescriptEvaluatorPresets
|
||||
@@ -361,7 +357,6 @@ export async function transformFixtureInput(
|
||||
'babel-plugin-idx',
|
||||
],
|
||||
sourceType: 'module',
|
||||
sourceMaps: includeSourceMaps,
|
||||
ast: includeEvaluator,
|
||||
cloneInputAst: includeEvaluator,
|
||||
configFile: false,
|
||||
@@ -452,7 +447,6 @@ export async function transformFixtureInput(
|
||||
forgetOutput,
|
||||
logs: formattedLogs,
|
||||
evaluatorCode,
|
||||
sourceMap: includeSourceMaps ? forgetResult.map : null,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {BabelFileResult} from '@babel/core';
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs';
|
||||
import invariant from 'invariant';
|
||||
@@ -25,7 +24,6 @@ export function writeOutputToString(
|
||||
evaluatorOutput: string | null,
|
||||
logs: string | null,
|
||||
errorMessage: string | null,
|
||||
sourceMap: BabelFileResult['map'] | null,
|
||||
) {
|
||||
// leading newline intentional
|
||||
let result = `
|
||||
@@ -44,14 +42,6 @@ ${wrapWithTripleBackticks(compilerOutput, 'javascript')}
|
||||
result += '\n';
|
||||
}
|
||||
|
||||
if (sourceMap != null) {
|
||||
result += `
|
||||
## Source Map
|
||||
|
||||
${wrapWithTripleBackticks(JSON.stringify(sourceMap, null, 2))}
|
||||
`;
|
||||
}
|
||||
|
||||
if (logs != null) {
|
||||
result += `
|
||||
## Logs
|
||||
|
||||
@@ -245,7 +245,6 @@ export async function transformFixture(
|
||||
sproutOutput,
|
||||
compileResult?.logs ?? null,
|
||||
error,
|
||||
compileResult?.sourceMap ?? null,
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -1670,6 +1670,37 @@ describe('ReactDOMForm', () => {
|
||||
expect(divRef.current.textContent).toEqual('Current username: acdlite');
|
||||
});
|
||||
|
||||
it('parallel form submissions do not throw', async () => {
|
||||
const formRef = React.createRef();
|
||||
let resolve = null;
|
||||
function App() {
|
||||
async function submitForm() {
|
||||
Scheduler.log('Action');
|
||||
if (!resolve) {
|
||||
await new Promise(res => {
|
||||
resolve = res;
|
||||
});
|
||||
}
|
||||
}
|
||||
return <form ref={formRef} action={submitForm} />;
|
||||
}
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await act(() => root.render(<App />));
|
||||
|
||||
// Start first form submission
|
||||
await act(async () => {
|
||||
formRef.current.requestSubmit();
|
||||
});
|
||||
assertLog(['Action']);
|
||||
|
||||
// Submit form again while first form action is still pending
|
||||
await act(async () => {
|
||||
formRef.current.requestSubmit();
|
||||
resolve(); // Resolve the promise to allow the first form action to complete
|
||||
});
|
||||
assertLog(['Action']);
|
||||
});
|
||||
|
||||
it(
|
||||
'requestFormReset works with inputs that are not descendants ' +
|
||||
'of the form element',
|
||||
|
||||
@@ -219,13 +219,13 @@ function addNestedProperty(
|
||||
return updatePayload;
|
||||
}
|
||||
|
||||
if (enableFastAddPropertiesInDiffing) {
|
||||
return fastAddProperties(updatePayload, nextProp, validAttributes);
|
||||
}
|
||||
|
||||
if (!isArray(nextProp)) {
|
||||
// Add each property of the leaf.
|
||||
if (enableFastAddPropertiesInDiffing) {
|
||||
return fastAddProperties(updatePayload, nextProp, validAttributes);
|
||||
} else {
|
||||
return addProperties(updatePayload, nextProp, validAttributes);
|
||||
}
|
||||
return slowAddProperties(updatePayload, nextProp, validAttributes);
|
||||
}
|
||||
|
||||
for (let i = 0; i < nextProp.length; i++) {
|
||||
@@ -516,7 +516,7 @@ function fastAddProperties(
|
||||
/**
|
||||
* addProperties adds all the valid props to the payload after being processed.
|
||||
*/
|
||||
function addProperties(
|
||||
function slowAddProperties(
|
||||
updatePayload: null | Object,
|
||||
props: Object,
|
||||
validAttributes: AttributeConfiguration,
|
||||
|
||||
10
packages/react-reconciler/src/ReactFiberHooks.js
vendored
10
packages/react-reconciler/src/ReactFiberHooks.js
vendored
@@ -3355,8 +3355,16 @@ export function requestFormReset(formFiber: Fiber) {
|
||||
);
|
||||
}
|
||||
|
||||
const stateHook = ensureFormComponentIsStateful(formFiber);
|
||||
let stateHook: Hook = ensureFormComponentIsStateful(formFiber);
|
||||
const newResetState = {};
|
||||
if (stateHook.next === null) {
|
||||
// Hack alert. If formFiber is the workInProgress Fiber then
|
||||
// we might get a broken intermediate state. Try the alternate
|
||||
// instead.
|
||||
// TODO: We should really stash the Queue somewhere stateful
|
||||
// just like how setState binds the Queue.
|
||||
stateHook = (formFiber.alternate: any).memoizedState;
|
||||
}
|
||||
const resetStateHook: Hook = (stateHook.next: any);
|
||||
const resetStateQueue = resetStateHook.queue;
|
||||
dispatchSetStateInternal(
|
||||
|
||||
Reference in New Issue
Block a user