[Flight][Reply] Close Response after creating root chunk (#27634)

creating the root after closing the response can lead to a promise that
never rejects. This is not intended use of the decodeReply API but if
pathalogical cases where you pass a raw FormData into this fucntion with
no zero chunk it can hang forever. This reordering causes a connection
error instead

---------

Co-authored-by: Zack Tanner <[email protected]>
This commit is contained in:
Josh Story
2023-10-31 18:31:10 -07:00
committed by GitHub
co-authored by Zack Tanner
parent ae1180d77b
commit 45525139ce
8 changed files with 24 additions and 7 deletions
@@ -162,8 +162,9 @@ function decodeReply<T>(
body = form;
}
const response = createResponse(moduleBasePath, '', body);
const root = getRoot<T>(response);
close(response);
return getRoot(response);
return root;
}
export {
@@ -93,8 +93,9 @@ function decodeReply<T>(
body = form;
}
const response = createResponse(turbopackMap, '', body);
const root = getRoot<T>(response);
close(response);
return getRoot(response);
return root;
}
export {renderToReadableStream, decodeReply, decodeAction};
@@ -93,8 +93,9 @@ function decodeReply<T>(
body = form;
}
const response = createResponse(turbopackMap, '', body);
const root = getRoot<T>(response);
close(response);
return getRoot(response);
return root;
}
export {renderToReadableStream, decodeReply, decodeAction};
@@ -158,8 +158,9 @@ function decodeReply<T>(
body = form;
}
const response = createResponse(turbopackMap, '', body);
const root = getRoot<T>(response);
close(response);
return getRoot(response);
return root;
}
export {
@@ -100,8 +100,9 @@ function decodeReply<T>(
body = form;
}
const response = createResponse(webpackMap, '', body);
const root = getRoot<T>(response);
close(response);
return getRoot(response);
return root;
}
export {renderToReadableStream, decodeReply, decodeAction, decodeFormState};
@@ -100,8 +100,9 @@ function decodeReply<T>(
body = form;
}
const response = createResponse(webpackMap, '', body);
const root = getRoot<T>(response);
close(response);
return getRoot(response);
return root;
}
export {renderToReadableStream, decodeReply, decodeAction, decodeFormState};
@@ -181,8 +181,9 @@ function decodeReply<T>(
body = form;
}
const response = createResponse(webpackMap, '', body);
const root = getRoot<T>(response);
close(response);
return getRoot(response);
return root;
}
export {
@@ -231,4 +231,14 @@ describe('ReactFlightDOMReply', () => {
expect(s2.has('hi')).toBe(true);
expect(s2).toEqual(s);
});
it('does not hang indefinitely when calling decodeReply with FormData', async () => {
let error;
try {
await ReactServerDOMServer.decodeReply(new FormData(), webpackServerMap);
} catch (e) {
error = e;
}
expect(error.message).toBe('Connection closed.');
});
});