import type {ReactClientValue} from 'react-server/src/ReactFlightServer';
export type ServerReference<T: Function> = T & {
$$typeof: symbol,
$$id: string,
$$bound: null | Array<ReactClientValue>,
$$location?: Error,
};
export type ClientReference<T> = {
$$typeof: symbol,
$$id: 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 registerClientReference<T>(
proxyImplementation: any,
id: string,
exportName: string,
): ClientReference<T> {
return Object.defineProperties(proxyImplementation, {
$$typeof: {value: CLIENT_REFERENCE_TAG},
$$id: {value: id + '#' + exportName},
});
}
const FunctionBind = Function.prototype.bind;
const ArraySlice = Array.prototype.slice;
function bind(this: ServerReference<any>): any {
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: any),
__DEV__
? {
$$typeof,
$$id,
$$bound,
$$location: {
value: this.$$location,
configurable: true,
},
bind: {value: bind, configurable: true},
}
: {
$$typeof,
$$id,
$$bound,
bind: {value: bind, configurable: true},
},
);
}
return newFn;
}
export function registerServerReference<T: Function>(
reference: T,
id: string,
exportName: string,
): ServerReference<T> {
const $$typeof = {value: SERVER_REFERENCE_TAG};
const $$id = {
value: id + '#' + exportName,
configurable: true,
};
const $$bound = {value: null, configurable: true};
return Object.defineProperties(
(reference: any),
__DEV__
? {
$$typeof,
$$id,
$$bound,
$$location: {
value: Error('react-stack-top-frame'),
configurable: true,
},
bind: {value: bind, configurable: true},
}
: {
$$typeof,
$$id,
$$bound,
bind: {value: bind, configurable: true},
},
);
}