From eb7570bc1631243af8df21c8a87173cc12f2d880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Thu, 22 Aug 2024 12:36:05 -0400 Subject: [PATCH] [Flight] Preserve location of bound server actions (#30778) Follow up to #30741. We need to keep the location of the action when it's bound so we can still jump to it. --- .../src/ReactFlightESMReferences.js | 38 +++++++++++++++---- .../src/ReactFlightTurbopackReferences.js | 37 +++++++++++++++--- .../src/ReactFlightWebpackReferences.js | 29 +++++++++++--- 3 files changed, 85 insertions(+), 19 deletions(-) diff --git a/packages/react-server-dom-esm/src/ReactFlightESMReferences.js b/packages/react-server-dom-esm/src/ReactFlightESMReferences.js index 86a25c7c8608a..0175ee913647c 100644 --- a/packages/react-server-dom-esm/src/ReactFlightESMReferences.js +++ b/packages/react-server-dom-esm/src/ReactFlightESMReferences.js @@ -52,14 +52,38 @@ function bind(this: ServerReference): any { // $FlowFixMe[unsupported-syntax] const newFn = FunctionBind.apply(this, arguments); if (this.$$typeof === SERVER_REFERENCE_TAG) { - // $FlowFixMe[method-unbinding] + 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); - return Object.defineProperties((newFn: any), { - $$typeof: {value: SERVER_REFERENCE_TAG}, - $$id: {value: this.$$id}, - $$bound: {value: this.$$bound ? this.$$bound.concat(args) : args}, - bind: {value: bind}, - }); + 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; } diff --git a/packages/react-server-dom-turbopack/src/ReactFlightTurbopackReferences.js b/packages/react-server-dom-turbopack/src/ReactFlightTurbopackReferences.js index 613a7e7dc862c..195f05ffa3cb6 100644 --- a/packages/react-server-dom-turbopack/src/ReactFlightTurbopackReferences.js +++ b/packages/react-server-dom-turbopack/src/ReactFlightTurbopackReferences.js @@ -66,13 +66,38 @@ function bind(this: ServerReference): any { // $FlowFixMe[unsupported-syntax] 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); - return Object.defineProperties((newFn: any), { - $$typeof: {value: SERVER_REFERENCE_TAG}, - $$id: {value: this.$$id}, - $$bound: {value: this.$$bound ? this.$$bound.concat(args) : args}, - bind: {value: bind}, - }); + 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; } diff --git a/packages/react-server-dom-webpack/src/ReactFlightWebpackReferences.js b/packages/react-server-dom-webpack/src/ReactFlightWebpackReferences.js index 025a7368213f8..195f05ffa3cb6 100644 --- a/packages/react-server-dom-webpack/src/ReactFlightWebpackReferences.js +++ b/packages/react-server-dom-webpack/src/ReactFlightWebpackReferences.js @@ -75,12 +75,29 @@ function bind(this: ServerReference): any { } } const args = ArraySlice.call(arguments, 1); - return Object.defineProperties((newFn: any), { - $$typeof: {value: SERVER_REFERENCE_TAG}, - $$id: {value: this.$$id}, - $$bound: {value: this.$$bound ? this.$$bound.concat(args) : args}, - bind: {value: bind}, - }); + 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; }