Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90ab3f89f4 | ||
|
|
63d61c7557 | ||
|
|
612e371fb2 | ||
|
|
fc5c53c396 |
@@ -7,18 +7,18 @@
|
||||
//
|
||||
// The @latest channel uses the version as-is, e.g.:
|
||||
//
|
||||
// 19.2.2
|
||||
// 19.2.4
|
||||
//
|
||||
// The @canary channel appends additional information, with the scheme
|
||||
// <version>-<label>-<commit_sha>, e.g.:
|
||||
//
|
||||
// 19.2.2-canary-a1c2d3e4
|
||||
// 19.2.4-canary-a1c2d3e4
|
||||
//
|
||||
// The @experimental channel doesn't include a version, only a date and a sha, e.g.:
|
||||
//
|
||||
// 0.0.0-experimental-241c4467e-20200129
|
||||
|
||||
const ReactVersion = '19.2.2';
|
||||
const ReactVersion = '19.2.4';
|
||||
|
||||
// The label used by the @canary channel. Represents the upcoming release's
|
||||
// stability. Most of the time, this will be "canary", but we may temporarily
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "react-art",
|
||||
"description": "React ART is a JavaScript library for drawing vector graphics using React. It provides declarative and reactive bindings to the ART library. Using the same declarative API you can render the output to either Canvas, SVG or VML (IE8).",
|
||||
"version": "19.2.2",
|
||||
"version": "19.2.4",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -27,7 +27,7 @@
|
||||
"scheduler": "^0.27.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^19.2.2"
|
||||
"react": "^19.2.4"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
|
||||
90
packages/react-client/src/ReactFlightClient.js
vendored
90
packages/react-client/src/ReactFlightClient.js
vendored
@@ -98,6 +98,8 @@ import getComponentNameFromType from 'shared/getComponentNameFromType';
|
||||
|
||||
import {getOwnerStackByComponentInfoInDev} from 'shared/ReactComponentInfoStack';
|
||||
|
||||
import hasOwnProperty from 'shared/hasOwnProperty';
|
||||
|
||||
import {injectInternals} from './ReactFlightClientDevToolsHook';
|
||||
|
||||
import {OMITTED_PROP_ERROR} from 'shared/ReactFlightPropertyAccess';
|
||||
@@ -163,6 +165,8 @@ const INITIALIZED = 'fulfilled';
|
||||
const ERRORED = 'rejected';
|
||||
const HALTED = 'halted'; // DEV-only. Means it never resolves even if connection closes.
|
||||
|
||||
const __PROTO__ = '__proto__';
|
||||
|
||||
type PendingChunk<T> = {
|
||||
status: 'pending',
|
||||
value: null | Array<InitializationReference | (T => mixed)>,
|
||||
@@ -1496,7 +1500,16 @@ function fulfillReference(
|
||||
}
|
||||
}
|
||||
}
|
||||
value = value[path[i]];
|
||||
const name = path[i];
|
||||
if (
|
||||
typeof value === 'object' &&
|
||||
value !== null &&
|
||||
hasOwnProperty.call(value, name)
|
||||
) {
|
||||
value = value[name];
|
||||
} else {
|
||||
throw new Error('Invalid reference.');
|
||||
}
|
||||
}
|
||||
|
||||
while (
|
||||
@@ -1532,7 +1545,9 @@ function fulfillReference(
|
||||
}
|
||||
|
||||
const mappedValue = map(response, value, parentObject, key);
|
||||
parentObject[key] = mappedValue;
|
||||
if (key !== __PROTO__) {
|
||||
parentObject[key] = mappedValue;
|
||||
}
|
||||
|
||||
// If this is the root object for a model reference, where `handler.value`
|
||||
// is a stale `null`, the resolved value can be used directly.
|
||||
@@ -1799,7 +1814,9 @@ function loadServerReference<A: Iterable<any>, T>(
|
||||
response._encodeFormAction,
|
||||
);
|
||||
|
||||
parentObject[key] = resolvedValue;
|
||||
if (key !== __PROTO__) {
|
||||
parentObject[key] = resolvedValue;
|
||||
}
|
||||
|
||||
// If this is the root object for a model reference, where `handler.value`
|
||||
// is a stale `null`, the resolved value can be used directly.
|
||||
@@ -2177,29 +2194,31 @@ function defineLazyGetter<T>(
|
||||
): any {
|
||||
// We don't immediately initialize it even if it's resolved.
|
||||
// Instead, we wait for the getter to get accessed.
|
||||
Object.defineProperty(parentObject, key, {
|
||||
get: function () {
|
||||
if (chunk.status === RESOLVED_MODEL) {
|
||||
// If it was now resolved, then we initialize it. This may then discover
|
||||
// a new set of lazy references that are then asked for eagerly in case
|
||||
// we get that deep.
|
||||
initializeModelChunk(chunk);
|
||||
}
|
||||
switch (chunk.status) {
|
||||
case INITIALIZED: {
|
||||
return chunk.value;
|
||||
if (key !== __PROTO__) {
|
||||
Object.defineProperty(parentObject, key, {
|
||||
get: function () {
|
||||
if (chunk.status === RESOLVED_MODEL) {
|
||||
// If it was now resolved, then we initialize it. This may then discover
|
||||
// a new set of lazy references that are then asked for eagerly in case
|
||||
// we get that deep.
|
||||
initializeModelChunk(chunk);
|
||||
}
|
||||
case ERRORED:
|
||||
throw chunk.reason;
|
||||
}
|
||||
// Otherwise, we didn't have enough time to load the object before it was
|
||||
// accessed or the connection closed. So we just log that it was omitted.
|
||||
// TODO: We should ideally throw here to indicate a difference.
|
||||
return OMITTED_PROP_ERROR;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
});
|
||||
switch (chunk.status) {
|
||||
case INITIALIZED: {
|
||||
return chunk.value;
|
||||
}
|
||||
case ERRORED:
|
||||
throw chunk.reason;
|
||||
}
|
||||
// Otherwise, we didn't have enough time to load the object before it was
|
||||
// accessed or the connection closed. So we just log that it was omitted.
|
||||
// TODO: We should ideally throw here to indicate a difference.
|
||||
return OMITTED_PROP_ERROR;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2510,14 +2529,16 @@ function parseModelString(
|
||||
// In DEV mode we encode omitted objects in logs as a getter that throws
|
||||
// so that when you try to access it on the client, you know why that
|
||||
// happened.
|
||||
Object.defineProperty(parentObject, key, {
|
||||
get: function () {
|
||||
// TODO: We should ideally throw here to indicate a difference.
|
||||
return OMITTED_PROP_ERROR;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
});
|
||||
if (key !== __PROTO__) {
|
||||
Object.defineProperty(parentObject, key, {
|
||||
get: function () {
|
||||
// TODO: We should ideally throw here to indicate a difference.
|
||||
return OMITTED_PROP_ERROR;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// Fallthrough
|
||||
@@ -5143,6 +5164,9 @@ function parseModel<T>(response: Response, json: UninitializedModel): T {
|
||||
function createFromJSONCallback(response: Response) {
|
||||
// $FlowFixMe[missing-this-annot]
|
||||
return function (key: string, value: JSONValue) {
|
||||
if (key === __PROTO__) {
|
||||
return undefined;
|
||||
}
|
||||
if (typeof value === 'string') {
|
||||
// We can't use .bind here because we need the "this" value.
|
||||
return parseModelString(response, this, key, value);
|
||||
|
||||
@@ -95,6 +95,8 @@ export type ReactServerValue =
|
||||
|
||||
type ReactServerObject = {+[key: string]: ReactServerValue};
|
||||
|
||||
const __PROTO__ = '__proto__';
|
||||
|
||||
function serializeByValueID(id: number): string {
|
||||
return '$' + id.toString(16);
|
||||
}
|
||||
@@ -361,6 +363,15 @@ export function processReply(
|
||||
): ReactJSONValue {
|
||||
const parent = this;
|
||||
|
||||
if (__DEV__) {
|
||||
if (key === __PROTO__) {
|
||||
console.error(
|
||||
'Expected not to serialize an object with own property `__proto__`. When parsed this property will be omitted.%s',
|
||||
describeObjectForErrorMessage(parent, key),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that `parent[key]` wasn't JSONified before `value` was passed to us
|
||||
if (__DEV__) {
|
||||
// $FlowFixMe[incompatible-use]
|
||||
@@ -780,6 +791,10 @@ export function processReply(
|
||||
if (typeof value === 'function') {
|
||||
const referenceClosure = knownServerReferences.get(value);
|
||||
if (referenceClosure !== undefined) {
|
||||
const existingReference = writtenObjects.get(value);
|
||||
if (existingReference !== undefined) {
|
||||
return existingReference;
|
||||
}
|
||||
const {id, bound} = referenceClosure;
|
||||
const referenceClosureJSON = JSON.stringify({id, bound}, resolveToJSON);
|
||||
if (formData === null) {
|
||||
@@ -789,7 +804,10 @@ export function processReply(
|
||||
// The reference to this function came from the same client so we can pass it back.
|
||||
const refId = nextPartId++;
|
||||
formData.set(formFieldPrefix + refId, referenceClosureJSON);
|
||||
return serializeServerReferenceID(refId);
|
||||
const serverReferenceId = serializeServerReferenceID(refId);
|
||||
// Store the server reference ID for deduplication.
|
||||
writtenObjects.set(value, serverReferenceId);
|
||||
return serverReferenceId;
|
||||
}
|
||||
if (temporaryReferences !== undefined && key.indexOf(':') === -1) {
|
||||
// TODO: If the property name contains a colon, we don't dedupe. Escape instead.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "react-dom-bindings",
|
||||
"description": "React implementation details for react-dom.",
|
||||
"version": "19.2.2",
|
||||
"version": "19.2.4",
|
||||
"private": true,
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-dom",
|
||||
"version": "19.2.2",
|
||||
"version": "19.2.4",
|
||||
"description": "React package for working with the DOM.",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
@@ -20,7 +20,7 @@
|
||||
"scheduler": "^0.27.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^19.2.2"
|
||||
"react": "^19.2.4"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-is",
|
||||
"version": "19.2.2",
|
||||
"version": "19.2.4",
|
||||
"description": "Brand checking of React Elements.",
|
||||
"main": "index.js",
|
||||
"sideEffects": false,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-markup",
|
||||
"version": "19.2.2",
|
||||
"version": "19.2.4",
|
||||
"description": "React package generating embedded markup such as e-mails with support for Server Components.",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^19.2.2"
|
||||
"react": "^19.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"scheduler": "^0.27.0"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "react-server-dom-esm",
|
||||
"description": "React Server Components bindings for DOM using ESM. This is intended to be integrated into meta-frameworks. It is not intended to be imported directly.",
|
||||
"version": "19.2.2",
|
||||
"version": "19.2.4",
|
||||
"keywords": [
|
||||
"react"
|
||||
],
|
||||
|
||||
@@ -332,12 +332,17 @@ function prerenderToNodeStream(
|
||||
function decodeReplyFromBusboy<T>(
|
||||
busboyStream: Busboy,
|
||||
moduleBasePath: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
const response = createResponse(
|
||||
moduleBasePath,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
undefined,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
let pendingFiles = 0;
|
||||
const queuedFields: Array<string> = [];
|
||||
@@ -403,7 +408,10 @@ function decodeReplyFromBusboy<T>(
|
||||
function decodeReply<T>(
|
||||
body: string | FormData,
|
||||
moduleBasePath: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
if (typeof body === 'string') {
|
||||
const form = new FormData();
|
||||
@@ -415,6 +423,7 @@ function decodeReply<T>(
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
body,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
const root = getRoot<T>(response);
|
||||
close(response);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "react-server-dom-parcel",
|
||||
"description": "React Server Components bindings for DOM using Parcel. This is intended to be integrated into meta-frameworks. It is not intended to be imported directly.",
|
||||
"version": "19.2.2",
|
||||
"version": "19.2.4",
|
||||
"keywords": [
|
||||
"react"
|
||||
],
|
||||
@@ -79,7 +79,7 @@
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^19.2.2",
|
||||
"react-dom": "^19.2.2"
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,10 @@ export function registerServerActions(manifest: ServerManifest) {
|
||||
|
||||
export function decodeReply<T>(
|
||||
body: string | FormData,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
if (typeof body === 'string') {
|
||||
const form = new FormData();
|
||||
@@ -260,6 +263,7 @@ export function decodeReply<T>(
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
body,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
const root = getRoot<T>(response);
|
||||
close(response);
|
||||
|
||||
@@ -253,7 +253,10 @@ export function registerServerActions(manifest: ServerManifest) {
|
||||
|
||||
export function decodeReply<T>(
|
||||
body: string | FormData,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
if (typeof body === 'string') {
|
||||
const form = new FormData();
|
||||
@@ -265,6 +268,7 @@ export function decodeReply<T>(
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
body,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
const root = getRoot<T>(response);
|
||||
close(response);
|
||||
|
||||
@@ -562,12 +562,17 @@ export function registerServerActions(manifest: ServerManifest) {
|
||||
|
||||
export function decodeReplyFromBusboy<T>(
|
||||
busboyStream: Busboy,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
const response = createResponse(
|
||||
serverManifest,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
undefined,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
let pendingFiles = 0;
|
||||
const queuedFields: Array<string> = [];
|
||||
@@ -632,7 +637,10 @@ export function decodeReplyFromBusboy<T>(
|
||||
|
||||
export function decodeReply<T>(
|
||||
body: string | FormData,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
if (typeof body === 'string') {
|
||||
const form = new FormData();
|
||||
@@ -644,6 +652,7 @@ export function decodeReply<T>(
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
body,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
const root = getRoot<T>(response);
|
||||
close(response);
|
||||
@@ -652,7 +661,10 @@ export function decodeReply<T>(
|
||||
|
||||
export function decodeReplyFromAsyncIterable<T>(
|
||||
iterable: AsyncIterable<[string, string | File]>,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
const iterator: AsyncIterator<[string, string | File]> =
|
||||
iterable[ASYNC_ITERATOR]();
|
||||
@@ -661,6 +673,8 @@ export function decodeReplyFromAsyncIterable<T>(
|
||||
serverManifest,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
undefined,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
|
||||
function progress(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "react-server-dom-turbopack",
|
||||
"description": "React Server Components bindings for DOM using Turbopack. This is intended to be integrated into meta-frameworks. It is not intended to be imported directly.",
|
||||
"version": "19.2.2",
|
||||
"version": "19.2.4",
|
||||
"keywords": [
|
||||
"react"
|
||||
],
|
||||
@@ -79,8 +79,8 @@
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^19.2.2",
|
||||
"react-dom": "^19.2.2"
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn-loose": "^8.3.0",
|
||||
|
||||
@@ -242,7 +242,10 @@ function prerender(
|
||||
function decodeReply<T>(
|
||||
body: string | FormData,
|
||||
turbopackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
if (typeof body === 'string') {
|
||||
const form = new FormData();
|
||||
@@ -254,6 +257,7 @@ function decodeReply<T>(
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
body,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
const root = getRoot<T>(response);
|
||||
close(response);
|
||||
|
||||
@@ -247,7 +247,10 @@ function prerender(
|
||||
function decodeReply<T>(
|
||||
body: string | FormData,
|
||||
turbopackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
if (typeof body === 'string') {
|
||||
const form = new FormData();
|
||||
@@ -259,6 +262,7 @@ function decodeReply<T>(
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
body,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
const root = getRoot<T>(response);
|
||||
close(response);
|
||||
@@ -268,7 +272,10 @@ function decodeReply<T>(
|
||||
function decodeReplyFromAsyncIterable<T>(
|
||||
iterable: AsyncIterable<[string, string | File]>,
|
||||
turbopackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
const iterator: AsyncIterator<[string, string | File]> =
|
||||
iterable[ASYNC_ITERATOR]();
|
||||
@@ -277,6 +284,8 @@ function decodeReplyFromAsyncIterable<T>(
|
||||
turbopackMap,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
undefined,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
|
||||
function progress(
|
||||
|
||||
@@ -554,12 +554,17 @@ function prerender(
|
||||
function decodeReplyFromBusboy<T>(
|
||||
busboyStream: Busboy,
|
||||
turbopackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
const response = createResponse(
|
||||
turbopackMap,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
undefined,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
let pendingFiles = 0;
|
||||
const queuedFields: Array<string> = [];
|
||||
@@ -625,7 +630,10 @@ function decodeReplyFromBusboy<T>(
|
||||
function decodeReply<T>(
|
||||
body: string | FormData,
|
||||
turbopackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
if (typeof body === 'string') {
|
||||
const form = new FormData();
|
||||
@@ -637,6 +645,7 @@ function decodeReply<T>(
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
body,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
const root = getRoot<T>(response);
|
||||
close(response);
|
||||
@@ -646,7 +655,10 @@ function decodeReply<T>(
|
||||
function decodeReplyFromAsyncIterable<T>(
|
||||
iterable: AsyncIterable<[string, string | File]>,
|
||||
turbopackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
const iterator: AsyncIterator<[string, string | File]> =
|
||||
iterable[ASYNC_ITERATOR]();
|
||||
@@ -655,6 +667,8 @@ function decodeReplyFromAsyncIterable<T>(
|
||||
turbopackMap,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
undefined,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
|
||||
function progress(
|
||||
|
||||
@@ -554,12 +554,17 @@ function prerender(
|
||||
function decodeReplyFromBusboy<T>(
|
||||
busboyStream: Busboy,
|
||||
webpackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
const response = createResponse(
|
||||
webpackMap,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
undefined,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
let pendingFiles = 0;
|
||||
const queuedFields: Array<string> = [];
|
||||
@@ -625,7 +630,10 @@ function decodeReplyFromBusboy<T>(
|
||||
function decodeReply<T>(
|
||||
body: string | FormData,
|
||||
webpackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
if (typeof body === 'string') {
|
||||
const form = new FormData();
|
||||
@@ -637,6 +645,7 @@ function decodeReply<T>(
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
body,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
const root = getRoot<T>(response);
|
||||
close(response);
|
||||
@@ -646,7 +655,10 @@ function decodeReply<T>(
|
||||
function decodeReplyFromAsyncIterable<T>(
|
||||
iterable: AsyncIterable<[string, string | File]>,
|
||||
webpackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
const iterator: AsyncIterator<[string, string | File]> =
|
||||
iterable[ASYNC_ITERATOR]();
|
||||
@@ -655,6 +667,8 @@ function decodeReplyFromAsyncIterable<T>(
|
||||
webpackMap,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
undefined,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
|
||||
function progress(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "react-server-dom-webpack",
|
||||
"description": "React Server Components bindings for DOM using Webpack. This is intended to be integrated into meta-frameworks. It is not intended to be imported directly.",
|
||||
"version": "19.2.2",
|
||||
"version": "19.2.4",
|
||||
"keywords": [
|
||||
"react"
|
||||
],
|
||||
@@ -85,8 +85,8 @@
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^19.2.2",
|
||||
"react-dom": "^19.2.2",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"webpack": "^5.59.0"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -242,7 +242,10 @@ function prerender(
|
||||
function decodeReply<T>(
|
||||
body: string | FormData,
|
||||
webpackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
if (typeof body === 'string') {
|
||||
const form = new FormData();
|
||||
@@ -254,6 +257,7 @@ function decodeReply<T>(
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
body,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
const root = getRoot<T>(response);
|
||||
close(response);
|
||||
|
||||
@@ -247,7 +247,10 @@ function prerender(
|
||||
function decodeReply<T>(
|
||||
body: string | FormData,
|
||||
webpackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
if (typeof body === 'string') {
|
||||
const form = new FormData();
|
||||
@@ -259,6 +262,7 @@ function decodeReply<T>(
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
body,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
const root = getRoot<T>(response);
|
||||
close(response);
|
||||
@@ -268,7 +272,10 @@ function decodeReply<T>(
|
||||
function decodeReplyFromAsyncIterable<T>(
|
||||
iterable: AsyncIterable<[string, string | File]>,
|
||||
webpackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
const iterator: AsyncIterator<[string, string | File]> =
|
||||
iterable[ASYNC_ITERATOR]();
|
||||
@@ -277,6 +284,8 @@ function decodeReplyFromAsyncIterable<T>(
|
||||
webpackMap,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
undefined,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
|
||||
function progress(
|
||||
|
||||
@@ -554,12 +554,17 @@ function prerender(
|
||||
function decodeReplyFromBusboy<T>(
|
||||
busboyStream: Busboy,
|
||||
webpackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
const response = createResponse(
|
||||
webpackMap,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
undefined,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
let pendingFiles = 0;
|
||||
const queuedFields: Array<string> = [];
|
||||
@@ -625,7 +630,10 @@ function decodeReplyFromBusboy<T>(
|
||||
function decodeReply<T>(
|
||||
body: string | FormData,
|
||||
webpackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
if (typeof body === 'string') {
|
||||
const form = new FormData();
|
||||
@@ -637,6 +645,7 @@ function decodeReply<T>(
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
body,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
const root = getRoot<T>(response);
|
||||
close(response);
|
||||
@@ -646,7 +655,10 @@ function decodeReply<T>(
|
||||
function decodeReplyFromAsyncIterable<T>(
|
||||
iterable: AsyncIterable<[string, string | File]>,
|
||||
webpackMap: ServerManifest,
|
||||
options?: {temporaryReferences?: TemporaryReferenceSet},
|
||||
options?: {
|
||||
temporaryReferences?: TemporaryReferenceSet,
|
||||
arraySizeLimit?: number,
|
||||
},
|
||||
): Thenable<T> {
|
||||
const iterator: AsyncIterator<[string, string | File]> =
|
||||
iterable[ASYNC_ITERATOR]();
|
||||
@@ -655,6 +667,8 @@ function decodeReplyFromAsyncIterable<T>(
|
||||
webpackMap,
|
||||
'',
|
||||
options ? options.temporaryReferences : undefined,
|
||||
undefined,
|
||||
options ? options.arraySizeLimit : undefined,
|
||||
);
|
||||
|
||||
function progress(
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import type {Thenable, ReactFormState} from 'shared/ReactTypes';
|
||||
import type {ReactFormState} from 'shared/ReactTypes';
|
||||
|
||||
import type {
|
||||
ServerManifest,
|
||||
@@ -20,26 +20,48 @@ import {
|
||||
requireModule,
|
||||
} from 'react-client/src/ReactFlightClientConfig';
|
||||
|
||||
import {createResponse, close, getRoot} from './ReactFlightReplyServer';
|
||||
import {
|
||||
createResponse,
|
||||
close,
|
||||
getRoot,
|
||||
MAX_BOUND_ARGS,
|
||||
} from './ReactFlightReplyServer';
|
||||
|
||||
type ServerReferenceId = any;
|
||||
|
||||
function bindArgs(fn: any, args: any) {
|
||||
if (args.length > MAX_BOUND_ARGS) {
|
||||
throw new Error(
|
||||
'Server Function has too many bound arguments. Received ' +
|
||||
args.length +
|
||||
' but the limit is ' +
|
||||
MAX_BOUND_ARGS +
|
||||
'.',
|
||||
);
|
||||
}
|
||||
|
||||
return fn.bind.apply(fn, [null].concat(args));
|
||||
}
|
||||
|
||||
function loadServerReference<T>(
|
||||
bundlerConfig: ServerManifest,
|
||||
id: ServerReferenceId,
|
||||
bound: null | Thenable<Array<any>>,
|
||||
metaData: {
|
||||
id: string,
|
||||
bound: null | Promise<Array<any>>,
|
||||
},
|
||||
): Promise<T> {
|
||||
const id: ServerReferenceId = metaData.id;
|
||||
if (typeof id !== 'string') {
|
||||
return (null: any);
|
||||
}
|
||||
const serverReference: ServerReference<T> =
|
||||
resolveServerReference<$FlowFixMe>(bundlerConfig, id);
|
||||
// We expect most servers to not really need this because you'd just have all
|
||||
// the relevant modules already loaded but it allows for lazy loading of code
|
||||
// if needed.
|
||||
const preloadPromise = preloadModule(serverReference);
|
||||
if (bound) {
|
||||
const bound = metaData.bound;
|
||||
if (bound instanceof Promise) {
|
||||
return Promise.all([(bound: any), preloadPromise]).then(
|
||||
([args]: Array<any>) => bindArgs(requireModule(serverReference), args),
|
||||
);
|
||||
@@ -57,6 +79,7 @@ function decodeBoundActionMetaData(
|
||||
body: FormData,
|
||||
serverManifest: ServerManifest,
|
||||
formFieldPrefix: string,
|
||||
arraySizeLimit: void | number,
|
||||
): {id: ServerReferenceId, bound: null | Promise<Array<any>>} {
|
||||
// The data for this reference is encoded in multiple fields under this prefix.
|
||||
const actionResponse = createResponse(
|
||||
@@ -64,6 +87,7 @@ function decodeBoundActionMetaData(
|
||||
formFieldPrefix,
|
||||
undefined,
|
||||
body,
|
||||
arraySizeLimit,
|
||||
);
|
||||
close(actionResponse);
|
||||
const refPromise = getRoot<{
|
||||
@@ -89,6 +113,7 @@ export function decodeAction<T>(
|
||||
const formData = new FormData();
|
||||
|
||||
let action: Promise<(formData: FormData) => T> | null = null;
|
||||
const seenActions = new Set<string>();
|
||||
|
||||
// $FlowFixMe[prop-missing]
|
||||
body.forEach((value: string | File, key: string) => {
|
||||
@@ -97,21 +122,36 @@ export function decodeAction<T>(
|
||||
formData.append(key, value);
|
||||
return;
|
||||
}
|
||||
// Later actions may override earlier actions if a button is used to override the default
|
||||
// form action.
|
||||
// Later actions may override earlier actions if a button is used to
|
||||
// override the default form action. However, we don't expect the same
|
||||
// action ref field to be sent multiple times in legitimate form data.
|
||||
if (key.startsWith('$ACTION_REF_')) {
|
||||
if (seenActions.has(key)) {
|
||||
return;
|
||||
}
|
||||
seenActions.add(key);
|
||||
const formFieldPrefix = '$ACTION_' + key.slice(12) + ':';
|
||||
const metaData = decodeBoundActionMetaData(
|
||||
body,
|
||||
serverManifest,
|
||||
formFieldPrefix,
|
||||
);
|
||||
action = loadServerReference(serverManifest, metaData.id, metaData.bound);
|
||||
action = loadServerReference(serverManifest, metaData);
|
||||
return;
|
||||
}
|
||||
// A simple action with no bound arguments may appear twice in the form data
|
||||
// if a button specifies the same action as the default form action. We only
|
||||
// load the first one, as they're guaranteed to be identical.
|
||||
if (key.startsWith('$ACTION_ID_')) {
|
||||
if (seenActions.has(key)) {
|
||||
return;
|
||||
}
|
||||
seenActions.add(key);
|
||||
const id = key.slice(11);
|
||||
action = loadServerReference(serverManifest, id, null);
|
||||
action = loadServerReference(serverManifest, {
|
||||
id,
|
||||
bound: null,
|
||||
});
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
785
packages/react-server/src/ReactFlightReplyServer.js
vendored
785
packages/react-server/src/ReactFlightReplyServer.js
vendored
File diff suppressed because it is too large
Load Diff
13
packages/react-server/src/ReactFlightServer.js
vendored
13
packages/react-server/src/ReactFlightServer.js
vendored
@@ -547,6 +547,8 @@ type DeferredDebugStore = {
|
||||
existing: Map<ReactClientReference | string, number>,
|
||||
};
|
||||
|
||||
const __PROTO__ = '__proto__';
|
||||
|
||||
const OPENING = 10;
|
||||
const OPEN = 11;
|
||||
const ABORTING = 12;
|
||||
@@ -3331,6 +3333,17 @@ function renderModelDestructive(
|
||||
// Set the currently rendering model
|
||||
task.model = value;
|
||||
|
||||
if (__DEV__) {
|
||||
if (parentPropertyName === __PROTO__) {
|
||||
callWithDebugContextInDEV(request, task, () => {
|
||||
console.error(
|
||||
'Expected not to serialize an object with own property `__proto__`. When parsed this property will be omitted.%s',
|
||||
describeObjectForErrorMessage(parent, parentPropertyName),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Special Symbol, that's very common.
|
||||
if (value === REACT_ELEMENT_TYPE) {
|
||||
return '$';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-test-renderer",
|
||||
"version": "19.2.2",
|
||||
"version": "19.2.4",
|
||||
"description": "React package for snapshot testing.",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
@@ -19,11 +19,11 @@
|
||||
},
|
||||
"homepage": "https://react.dev/",
|
||||
"dependencies": {
|
||||
"react-is": "^19.2.2",
|
||||
"react-is": "^19.2.4",
|
||||
"scheduler": "^0.27.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^19.2.2"
|
||||
"react": "^19.2.4"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"keywords": [
|
||||
"react"
|
||||
],
|
||||
"version": "19.2.2",
|
||||
"version": "19.2.4",
|
||||
"homepage": "https://react.dev/",
|
||||
"bugs": "https://github.com/facebook/react/issues",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -12,4 +12,4 @@
|
||||
// TODO: This module is used both by the release scripts and to expose a version
|
||||
// at runtime. We should instead inject the version number as part of the build
|
||||
// process, and use the ReactVersions.js module as the single source of truth.
|
||||
export default '19.2.2';
|
||||
export default '19.2.4';
|
||||
|
||||
@@ -555,5 +555,16 @@
|
||||
"567": "Already initialized stream.",
|
||||
"568": "Already initialized typed array.",
|
||||
"569": "Cannot have cyclic thenables.",
|
||||
"570": "Invalid reference."
|
||||
"570": "Invalid reference.",
|
||||
"571": "Maximum array nesting exceeded. Large nested arrays can be dangerous. Try adding intermediate objects.",
|
||||
"572": "Already initialized Map.",
|
||||
"573": "Already initialized Set.",
|
||||
"574": "Invalid forward reference.",
|
||||
"575": "Invalid Map initializer.",
|
||||
"576": "Invalid Set initializer.",
|
||||
"577": "Invalid Iterator initializer.",
|
||||
"578": "Already initialized Iterator.",
|
||||
"579": "Invalid data for bytes stream.",
|
||||
"580": "Server Function has too many bound arguments. Received %s but the limit is %s.",
|
||||
"581": "BigInt is too large. Received %s digits but the limit is %s."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user