react/packages/react-server-dom-webpack/src/ReactFlightServerConfigWebpackBundler.js
Sophie Alpert 767f52237c
Use .slice() for all substring-ing (#26677)
- substr is Annex B
- substring silently flips its arguments if they're in the "wrong order", which is confusing
- slice is better than sliced bread (no pun intended) and also it works the same way on Arrays so there's less to remember

---

> I'd be down to just lint and enforce a single form just for the potential compression savings by using a repeated string.

_Originally posted by @sebmarkbage in https://github.com/facebook/react/pull/26663#discussion_r1170455401_
2023-04-19 14:26:01 -07:00

107 lines
2.9 KiB
JavaScript

/**
* 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.
*
* @flow
*/
import type {ReactClientValue} from 'react-server/src/ReactFlightServer';
export type ClientManifest = {
[id: string]: ClientReferenceMetadata,
};
export type ServerReference<T: Function> = T & {
$$typeof: symbol,
$$id: string,
$$bound: null | Array<ReactClientValue>,
};
export type ServerReferenceId = string;
// eslint-disable-next-line no-unused-vars
export type ClientReference<T> = {
$$typeof: symbol,
$$id: string,
$$async: boolean,
};
export type ClientReferenceMetadata = {
id: string,
chunks: Array<string>,
name: string,
async: boolean,
};
export type ClientReferenceKey = string;
const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
const SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');
export function getClientReferenceKey(
reference: ClientReference<any>,
): ClientReferenceKey {
return reference.$$async ? reference.$$id + '#async' : reference.$$id;
}
export function isClientReference(reference: Object): boolean {
return reference.$$typeof === CLIENT_REFERENCE_TAG;
}
export function isServerReference(reference: Object): boolean {
return reference.$$typeof === SERVER_REFERENCE_TAG;
}
export function resolveClientReferenceMetadata<T>(
config: ClientManifest,
clientReference: ClientReference<T>,
): ClientReferenceMetadata {
const modulePath = clientReference.$$id;
let name = '';
let resolvedModuleData = config[modulePath];
if (resolvedModuleData) {
// The potentially aliased name.
name = resolvedModuleData.name;
} else {
// We didn't find this specific export name but we might have the * export
// which contains this name as well.
// TODO: It's unfortunate that we now have to parse this string. We should
// probably go back to encoding path and name separately on the client reference.
const idx = modulePath.lastIndexOf('#');
if (idx !== -1) {
name = modulePath.slice(idx + 1);
resolvedModuleData = config[modulePath.slice(0, idx)];
}
if (!resolvedModuleData) {
throw new Error(
'Could not find the module "' +
modulePath +
'" in the React Client Manifest. ' +
'This is probably a bug in the React Server Components bundler.',
);
}
}
return {
id: resolvedModuleData.id,
chunks: resolvedModuleData.chunks,
name: name,
async: !!clientReference.$$async,
};
}
export function getServerReferenceId<T>(
config: ClientManifest,
serverReference: ServerReference<T>,
): ServerReferenceId {
return serverReference.$$id;
}
export function getServerReferenceBoundArguments<T>(
config: ClientManifest,
serverReference: ServerReference<T>,
): null | Array<ReactClientValue> {
return serverReference.$$bound;
}