1. /**
    
  2.  * Copyright (c) Meta Platforms, Inc. and affiliates.
    
  3.  *
    
  4.  * This source code is licensed under the MIT license found in the
    
  5.  * LICENSE file in the root directory of this source tree.
    
  6.  *
    
  7.  * @flow
    
  8.  */
    
  9. 
    
  10. import type {ReactClientValue} from 'react-server/src/ReactFlightServer';
    
  11. 
    
  12. export type ServerReference<T: Function> = T & {
    
  13.   $$typeof: symbol,
    
  14.   $$id: string,
    
  15.   $$bound: null | Array<ReactClientValue>,
    
  16. };
    
  17. 
    
  18. // eslint-disable-next-line no-unused-vars
    
  19. export type ClientReference<T> = {
    
  20.   $$typeof: symbol,
    
  21.   $$id: string,
    
  22. };
    
  23. 
    
  24. const CLIENT_REFERENCE_TAG = Symbol.for('react.client.reference');
    
  25. const SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');
    
  26. 
    
  27. export function isClientReference(reference: Object): boolean {
    
  28.   return reference.$$typeof === CLIENT_REFERENCE_TAG;
    
  29. }
    
  30. 
    
  31. export function isServerReference(reference: Object): boolean {
    
  32.   return reference.$$typeof === SERVER_REFERENCE_TAG;
    
  33. }
    
  34. 
    
  35. export function registerClientReference<T>(
    
  36.   proxyImplementation: any,
    
  37.   id: string,
    
  38.   exportName: string,
    
  39. ): ClientReference<T> {
    
  40.   return Object.defineProperties(proxyImplementation, {
    
  41.     $$typeof: {value: CLIENT_REFERENCE_TAG},
    
  42.     $$id: {value: id + '#' + exportName},
    
  43.   });
    
  44. }
    
  45. 
    
  46. // $FlowFixMe[method-unbinding]
    
  47. const FunctionBind = Function.prototype.bind;
    
  48. // $FlowFixMe[method-unbinding]
    
  49. const ArraySlice = Array.prototype.slice;
    
  50. function bind(this: ServerReference<any>) {
    
  51.   // $FlowFixMe[unsupported-syntax]
    
  52.   const newFn = FunctionBind.apply(this, arguments);
    
  53.   if (this.$$typeof === SERVER_REFERENCE_TAG) {
    
  54.     // $FlowFixMe[method-unbinding]
    
  55.     const args = ArraySlice.call(arguments, 1);
    
  56.     newFn.$$typeof = SERVER_REFERENCE_TAG;
    
  57.     newFn.$$id = this.$$id;
    
  58.     newFn.$$bound = this.$$bound ? this.$$bound.concat(args) : args;
    
  59.   }
    
  60.   return newFn;
    
  61. }
    
  62. 
    
  63. export function registerServerReference<T>(
    
  64.   reference: ServerReference<T>,
    
  65.   id: string,
    
  66.   exportName: string,
    
  67. ): ServerReference<T> {
    
  68.   return Object.defineProperties((reference: any), {
    
  69.     $$typeof: {value: SERVER_REFERENCE_TAG},
    
  70.     $$id: {value: id + '#' + exportName},
    
  71.     $$bound: {value: null},
    
  72.     bind: {value: bind},
    
  73.   });
    
  74. }