/** * 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 ServerReference = T & { $$typeof: symbol, $$id: string, $$bound: null | Array, $$location?: Error, }; // eslint-disable-next-line no-unused-vars export type ClientReference = { $$typeof: symbol, $$id: string, $$name: string, $$bundles: Array, $$importMap?: ?{[string]: string}, }; const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference'); const SERVER_REFERENCE_TAG = Symbol.for('react.server.reference'); 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 createClientReference( id: string, exportName: string, bundles: Array, importMap?: ?{[string]: string}, ): ClientReference { return { $$typeof: CLIENT_REFERENCE_TAG, $$id: id, $$name: exportName, $$bundles: bundles, $$importMap: importMap, }; } // $FlowFixMe[method-unbinding] const FunctionBind = Function.prototype.bind; // $FlowFixMe[method-unbinding] const ArraySlice = Array.prototype.slice; function bind(this: ServerReference): any { // $FlowFixMe[incompatible-type] const newFn = FunctionBind.apply(this, arguments); if (this.$$typeof === SERVER_REFERENCE_TAG) { if (__DEV__) { const thisBind = arguments[0]; if (thisBind != null) { console.error( 'Cannot bind "this" of a Server Action. Pass null or undefined as the first argument to .bind().', ); } } const args = ArraySlice.call(arguments, 1); const $$typeof = {value: SERVER_REFERENCE_TAG}; const $$id = {value: this.$$id}; const $$bound = {value: this.$$bound ? this.$$bound.concat(args) : args}; return Object.defineProperties( newFn as any, (__DEV__ ? { $$typeof, $$id, $$bound, $$location: { value: this.$$location, configurable: true, }, bind: {value: bind, configurable: true}, } : { $$typeof, $$id, $$bound, bind: {value: bind, configurable: true}, }) as PropertyDescriptorMap, ); } return newFn; } const serverReferenceToString = { value: () => 'function () { [omitted code] }', configurable: true, writable: true, }; export function registerServerReference( reference: ServerReference, id: string, exportName: string, ): ServerReference { const $$typeof = {value: SERVER_REFERENCE_TAG}; const $$id = { value: id + '#' + exportName, configurable: true, }; const $$bound = {value: null, configurable: true}; return Object.defineProperties( reference as any, (__DEV__ ? { $$typeof, $$id, $$bound, $$location: { value: Error('react-stack-top-frame'), configurable: true, }, bind: {value: bind, configurable: true}, toString: serverReferenceToString, } : { $$typeof, $$id, $$bound, bind: {value: bind, configurable: true}, toString: serverReferenceToString, }) as PropertyDescriptorMap, ); }