diff --git a/crates/next-custom-transforms/src/transforms/server_actions.rs b/crates/next-custom-transforms/src/transforms/server_actions.rs index 49cf8465cb079..9db269ff46a2a 100644 --- a/crates/next-custom-transforms/src/transforms/server_actions.rs +++ b/crates/next-custom-transforms/src/transforms/server_actions.rs @@ -214,7 +214,7 @@ impl ServerActions { ); let register_action_expr = bind_args_to_ref_expr( - annotate_ident_as_server_reference(action_ident.clone(), action_id.clone()), + annotate_ident_as_server_reference(action_ident.clone(), action_id.clone(), arrow.span), ids_from_closure .iter() .cloned() @@ -377,7 +377,11 @@ impl ServerActions { let action_id = generate_action_id(&self.config.hash_salt, &self.file_name, &action_name); let register_action_expr = bind_args_to_ref_expr( - annotate_ident_as_server_reference(action_ident.clone(), action_id.clone()), + annotate_ident_as_server_reference( + action_ident.clone(), + action_id.clone(), + function.span, + ), ids_from_closure .iter() .cloned() @@ -652,14 +656,21 @@ impl ServerActions { .into(), }))); + if let Some(Ident { sym, .. }) = &self.arrow_or_fn_expr_ident { + assign_name_to_ident(&cache_ident, sym.as_str(), &mut self.hoisted_extra_items); + } + let bound_args: Vec<_> = ids_from_closure .iter() .cloned() .map(|id| Some(id.as_arg())) .collect(); - let register_action_expr = - annotate_ident_as_server_reference(cache_ident.clone(), reference_id.clone()); + let register_action_expr = annotate_ident_as_server_reference( + cache_ident.clone(), + reference_id.clone(), + arrow.span, + ); // If there're any bound args from the closure, we need to hoist the // register action expression to the top-level, and return the bind @@ -709,8 +720,11 @@ impl ServerActions { let reference_id = generate_action_id(&self.config.hash_salt, &self.file_name, &cache_name); - let register_action_expr = - annotate_ident_as_server_reference(cache_ident.clone(), reference_id.clone()); + let register_action_expr = annotate_ident_as_server_reference( + cache_ident.clone(), + reference_id.clone(), + function.span, + ); function.body.visit_mut_with(&mut ClosureReplacer { used_ids: &ids_from_closure, @@ -805,7 +819,7 @@ impl ServerActions { name: Pat::Ident(cache_ident.clone().into()), init: Some(wrap_cache_expr( Box::new(Expr::Fn(FnExpr { - ident: fn_name, + ident: fn_name.clone(), function: Box::new(Function { params: new_params, body: new_body, @@ -822,6 +836,12 @@ impl ServerActions { .into(), }))); + if let Some(Ident { sym, .. }) = fn_name { + assign_name_to_ident(&cache_ident, sym.as_str(), &mut self.hoisted_extra_items); + } else if self.in_default_export_decl { + assign_name_to_ident(&cache_ident, "default", &mut self.hoisted_extra_items); + } + let bound_args: Vec<_> = ids_from_closure .iter() .cloned() @@ -947,16 +967,6 @@ impl VisitMut for ServerActions { } if let Some(cache_type_str) = cache_type { - // It's a cache function. If it doesn't have a name, give it one. - match f.ident.as_mut() { - None => { - let action_name = gen_cache_ident(&mut self.reference_index); - let ident = Ident::new(action_name, DUMMY_SP, Default::default()); - f.ident.insert(ident) - } - Some(i) => i, - }; - // Collect all the identifiers defined inside the closure and used // in the cache function. With deduplication. retain_names_from_declared_idents( @@ -966,7 +976,7 @@ impl VisitMut for ServerActions { let new_expr = self.maybe_hoist_and_create_proxy_for_cache_function( child_names.clone(), - f.ident.clone(), + f.ident.clone().or(self.arrow_or_fn_expr_ident.clone()), cache_type_str.as_str(), &mut f.function, ); @@ -1489,7 +1499,7 @@ impl VisitMut for ServerActions { self.exported_idents .push((new_ident.clone(), "default".into())); - attach_name_to_default_expr(&new_ident, &mut self.extra_items); + assign_name_to_ident(&new_ident, "default", &mut self.extra_items); } } _ => { @@ -1514,7 +1524,7 @@ impl VisitMut for ServerActions { .push((new_ident.clone(), "default".into())); create_var_declarator(&new_ident, &mut self.extra_items); - attach_name_to_default_expr(&new_ident, &mut self.extra_items); + assign_name_to_ident(&new_ident, "default", &mut self.extra_items); *default_expr.expr = assign_arrow_expr(&new_ident, Expr::Arrow(arrow.clone())); @@ -1538,7 +1548,7 @@ impl VisitMut for ServerActions { .push((new_ident.clone(), "default".into())); create_var_declarator(&new_ident, &mut self.extra_items); - attach_name_to_default_expr(&new_ident, &mut self.extra_items); + assign_name_to_ident(&new_ident, "default", &mut self.extra_items); *default_expr.expr = assign_arrow_expr(&new_ident, Expr::Call(call.clone())); @@ -1726,6 +1736,7 @@ impl VisitMut for ServerActions { expr: Box::new(annotate_ident_as_server_reference( ident.clone(), action_id, + ident.span, )), })); } @@ -2079,7 +2090,7 @@ fn create_var_declarator(ident: &Ident, extra_items: &mut Vec) { }))))); } -fn attach_name_to_default_expr(ident: &Ident, extra_items: &mut Vec) { +fn assign_name_to_ident(ident: &Ident, name: &str, extra_items: &mut Vec) { // Assign a name with `Object.defineProperty($$ACTION_0, 'name', {value: 'default'})` extra_items.push(ModuleItem::Stmt(Stmt::Expr(ExprStmt { span: DUMMY_SP, @@ -2110,7 +2121,7 @@ fn attach_name_to_default_expr(ident: &Ident, extra_items: &mut Vec) props: vec![ PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { key: PropName::Str("value".into()), - value: Box::new("default".into()), + value: Box::new(name.into()), }))), PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { key: PropName::Str("writable".into()), @@ -2155,10 +2166,14 @@ fn generate_action_id(hash_salt: &str, file_name: &str, export_name: &str) -> St hex_encode(result) } -fn annotate_ident_as_server_reference(ident: Ident, action_id: String) -> Expr { +fn annotate_ident_as_server_reference( + ident: Ident, + action_id: String, + original_span: Span, +) -> Expr { // registerServerReference(reference, id, null) Expr::Call(CallExpr { - span: ident.span, + span: original_span, callee: quote_ident!("registerServerReference").as_callee(), args: vec![ ExprOrSpread { diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server/33/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server/33/output.js index d946877ad2236..4743ed48dea1f 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server/33/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server/33/output.js @@ -5,6 +5,10 @@ const v = 'world'; export var $$RSC_SERVER_CACHE_0 = $$cache__("default", "3128060c414d59f8552e4788b846c0d2b7f74743", async function fn() { return 'hello, ' + v; }); +Object.defineProperty($$RSC_SERVER_CACHE_0, "name", { + "value": "fn", + "writable": false +}); var fn = registerServerReference($$RSC_SERVER_CACHE_0, "3128060c414d59f8552e4788b846c0d2b7f74743", null); export async function Component() { const data = await fn(); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server/34/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server/34/output.js index e59052890ce73..e33c2754dca1d 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server/34/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server/34/output.js @@ -1,26 +1,42 @@ -/* __next_internal_action_entry_do_not_use__ {"12a8d21b6362b4cc8f5b15560525095bc48dba80":"$$RSC_SERVER_CACHE_3","3128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0","4acc55633206134002149ce873fe498be64a6fef":"$$RSC_SERVER_CACHE_4","951c375b4a6a6e89d67b743ec5808127cfde405d":"$$RSC_SERVER_CACHE_1"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"12a8d21b6362b4cc8f5b15560525095bc48dba80":"$$RSC_SERVER_CACHE_3","3128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0","69348c79fce073bae2f70f139565a2fda1c74c74":"$$RSC_SERVER_CACHE_2","951c375b4a6a6e89d67b743ec5808127cfde405d":"$$RSC_SERVER_CACHE_1"} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; export var $$RSC_SERVER_CACHE_0 = $$cache__("default", "3128060c414d59f8552e4788b846c0d2b7f74743", async function() { return 'foo'; }); +Object.defineProperty($$RSC_SERVER_CACHE_0, "name", { + "value": "foo", + "writable": false +}); const foo = registerServerReference($$RSC_SERVER_CACHE_0, "3128060c414d59f8552e4788b846c0d2b7f74743", null); export { bar }; export var $$RSC_SERVER_CACHE_1 = $$cache__("default", "951c375b4a6a6e89d67b743ec5808127cfde405d", async function bar() { return 'bar'; }); +Object.defineProperty($$RSC_SERVER_CACHE_1, "name", { + "value": "bar", + "writable": false +}); var bar = registerServerReference($$RSC_SERVER_CACHE_1, "951c375b4a6a6e89d67b743ec5808127cfde405d", null); // Should not be wrapped in $$cache__. const qux = async function qux() { return 'qux'; }; -export var $$RSC_SERVER_CACHE_3 = $$cache__("default", "12a8d21b6362b4cc8f5b15560525095bc48dba80", async function $$RSC_SERVER_CACHE_2() { +export var $$RSC_SERVER_CACHE_2 = $$cache__("default", "69348c79fce073bae2f70f139565a2fda1c74c74", async function baz() { return qux() + 'baz'; }); -const baz = registerServerReference($$RSC_SERVER_CACHE_3, "12a8d21b6362b4cc8f5b15560525095bc48dba80", null); -export var $$RSC_SERVER_CACHE_4 = $$cache__("default", "4acc55633206134002149ce873fe498be64a6fef", async function() { +Object.defineProperty($$RSC_SERVER_CACHE_2, "name", { + "value": "baz", + "writable": false +}); +const baz = registerServerReference($$RSC_SERVER_CACHE_2, "69348c79fce073bae2f70f139565a2fda1c74c74", null); +export var $$RSC_SERVER_CACHE_3 = $$cache__("default", "12a8d21b6362b4cc8f5b15560525095bc48dba80", async function() { return 'quux'; }); -const quux = registerServerReference($$RSC_SERVER_CACHE_4, "4acc55633206134002149ce873fe498be64a6fef", null); +Object.defineProperty($$RSC_SERVER_CACHE_3, "name", { + "value": "quux", + "writable": false +}); +const quux = registerServerReference($$RSC_SERVER_CACHE_3, "12a8d21b6362b4cc8f5b15560525095bc48dba80", null); export { foo, baz }; export default quux; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server/35/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server/35/output.js index c8abbfed26710..c4eec6775c9a4 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server/35/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server/35/output.js @@ -4,4 +4,8 @@ import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; export var $$RSC_SERVER_CACHE_0 = $$cache__("default", "3128060c414d59f8552e4788b846c0d2b7f74743", async function() { return 'data'; }); +Object.defineProperty($$RSC_SERVER_CACHE_0, "name", { + "value": "my_fn", + "writable": false +}); export const my_fn = registerServerReference($$RSC_SERVER_CACHE_0, "3128060c414d59f8552e4788b846c0d2b7f74743", null); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server/36/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server/36/output.js index bc293332ceb89..09f64812ebc68 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server/36/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server/36/output.js @@ -1,19 +1,35 @@ -/* __next_internal_action_entry_do_not_use__ {"3128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0","4acc55633206134002149ce873fe498be64a6fef":"$$RSC_SERVER_CACHE_4","69348c79fce073bae2f70f139565a2fda1c74c74":"$$RSC_SERVER_CACHE_2","951c375b4a6a6e89d67b743ec5808127cfde405d":"$$RSC_SERVER_CACHE_1"} */ import { registerServerReference } from "private-next-rsc-server-reference"; +/* __next_internal_action_entry_do_not_use__ {"12a8d21b6362b4cc8f5b15560525095bc48dba80":"$$RSC_SERVER_CACHE_3","3128060c414d59f8552e4788b846c0d2b7f74743":"$$RSC_SERVER_CACHE_0","69348c79fce073bae2f70f139565a2fda1c74c74":"$$RSC_SERVER_CACHE_2","951c375b4a6a6e89d67b743ec5808127cfde405d":"$$RSC_SERVER_CACHE_1"} */ import { registerServerReference } from "private-next-rsc-server-reference"; import { encryptActionBoundArgs, decryptActionBoundArgs } from "private-next-rsc-action-encryption"; import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; export var $$RSC_SERVER_CACHE_0 = $$cache__("default", "3128060c414d59f8552e4788b846c0d2b7f74743", async function foo() { return 'data A'; }); +Object.defineProperty($$RSC_SERVER_CACHE_0, "name", { + "value": "foo", + "writable": false +}); export var foo = registerServerReference($$RSC_SERVER_CACHE_0, "3128060c414d59f8552e4788b846c0d2b7f74743", null); export var $$RSC_SERVER_CACHE_1 = $$cache__("default", "951c375b4a6a6e89d67b743ec5808127cfde405d", async function bar() { return 'data B'; }); +Object.defineProperty($$RSC_SERVER_CACHE_1, "name", { + "value": "bar", + "writable": false +}); export var bar = registerServerReference($$RSC_SERVER_CACHE_1, "951c375b4a6a6e89d67b743ec5808127cfde405d", null); export var $$RSC_SERVER_CACHE_2 = $$cache__("default", "69348c79fce073bae2f70f139565a2fda1c74c74", async function Cached({ children }) { return children; }); +Object.defineProperty($$RSC_SERVER_CACHE_2, "name", { + "value": "Cached", + "writable": false +}); export default registerServerReference($$RSC_SERVER_CACHE_2, "69348c79fce073bae2f70f139565a2fda1c74c74", null); -export var $$RSC_SERVER_CACHE_4 = $$cache__("default", "4acc55633206134002149ce873fe498be64a6fef", async function $$RSC_SERVER_CACHE_3() { +export var $$RSC_SERVER_CACHE_3 = $$cache__("default", "12a8d21b6362b4cc8f5b15560525095bc48dba80", async function baz() { return 'data C'; }); -export const baz = registerServerReference($$RSC_SERVER_CACHE_4, "4acc55633206134002149ce873fe498be64a6fef", null); +Object.defineProperty($$RSC_SERVER_CACHE_3, "name", { + "value": "baz", + "writable": false +}); +export const baz = registerServerReference($$RSC_SERVER_CACHE_3, "12a8d21b6362b4cc8f5b15560525095bc48dba80", null); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server/37/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server/37/output.js index 6c87b5a00e67c..ad6c82a7ab063 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server/37/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server/37/output.js @@ -4,6 +4,10 @@ import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; export var $$RSC_SERVER_CACHE_0 = $$cache__("default", "3128060c414d59f8552e4788b846c0d2b7f74743", async function fn() { return 'foo'; }); +Object.defineProperty($$RSC_SERVER_CACHE_0, "name", { + "value": "fn", + "writable": false +}); var fn = registerServerReference($$RSC_SERVER_CACHE_0, "3128060c414d59f8552e4788b846c0d2b7f74743", null); async function Component() { const data = await fn(); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server/38/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server/38/output.js index b0b725ebaa0b0..5a2a7ce14af65 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server/38/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server/38/output.js @@ -4,4 +4,8 @@ import { cache as $$cache__ } from "private-next-rsc-cache-wrapper"; export var $$RSC_SERVER_CACHE_0 = $$cache__("x", "3128060c414d59f8552e4788b846c0d2b7f74743", async function foo() { return 'data'; }); +Object.defineProperty($$RSC_SERVER_CACHE_0, "name", { + "value": "foo", + "writable": false +}); export var foo = registerServerReference($$RSC_SERVER_CACHE_0, "3128060c414d59f8552e4788b846c0d2b7f74743", null); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server/39/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server/39/output.js index 212eabc90711d..944a9d0fbd2cf 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server/39/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server/39/output.js @@ -8,6 +8,10 @@ export var $$RSC_SERVER_CACHE_0 = $$cache__("default", "3128060c414d59f8552e4788 foo: $$ACTION_ARG_1 }; }); +Object.defineProperty($$RSC_SERVER_CACHE_0, "name", { + "value": "fn", + "writable": false +}); async function Component({ foo }) { const a = 123; var fn = $$RSC_SERVER_REF_1.bind(null, encryptActionBoundArgs("3128060c414d59f8552e4788b846c0d2b7f74743", [ diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server/40/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server/40/output.js index 3363437cd50ea..44e54e3305788 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server/40/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server/40/output.js @@ -11,6 +11,10 @@ export var $$RSC_SERVER_CACHE_0 = $$cache__("default", "3128060c414d59f8552e4788 } ]; }); +Object.defineProperty($$RSC_SERVER_CACHE_0, "name", { + "value": "cache", + "writable": false +}); export const $$RSC_SERVER_ACTION_2 = async function action($$ACTION_CLOSURE_BOUND, c) { var [$$ACTION_ARG_0, $$ACTION_ARG_1] = await decryptActionBoundArgs("1c36b06e398c97abe5d5d7ae8c672bfddf4e1b91", $$ACTION_CLOSURE_BOUND); const d = $$ACTION_ARG_0 + $$ACTION_ARG_1 + c; diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server/41/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server/41/output.js index 61a8df5b92db2..5633a68e84828 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server/41/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server/41/output.js @@ -17,4 +17,8 @@ export var $$RSC_SERVER_CACHE_1 = $$cache__("default", "951c375b4a6a6e89d67b743e const data = await fn(); return
{data}
; }); +Object.defineProperty($$RSC_SERVER_CACHE_1, "name", { + "value": "Component", + "writable": false +}); export var Component = registerServerReference($$RSC_SERVER_CACHE_1, "951c375b4a6a6e89d67b743ec5808127cfde405d", null); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server/43/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server/43/output.js index 725ee4f98cb6f..2c138ee83b9e4 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server/43/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server/43/output.js @@ -17,4 +17,8 @@ export var $$RSC_SERVER_CACHE_1 = $$cache__("default", "951c375b4a6a6e89d67b743e r: children }; }); +Object.defineProperty($$RSC_SERVER_CACHE_1, "name", { + "value": "getCachedRandom", + "writable": false +}); var getCachedRandom = registerServerReference($$RSC_SERVER_CACHE_1, "951c375b4a6a6e89d67b743ec5808127cfde405d", null); diff --git a/crates/next-custom-transforms/tests/fixture/server-actions/server/45/output.js b/crates/next-custom-transforms/tests/fixture/server-actions/server/45/output.js index f093af51af6f0..5661cb7b69c30 100644 --- a/crates/next-custom-transforms/tests/fixture/server-actions/server/45/output.js +++ b/crates/next-custom-transforms/tests/fixture/server-actions/server/45/output.js @@ -10,4 +10,8 @@ function Foo() { export var $$RSC_SERVER_CACHE_0 = $$cache__("default", "3128060c414d59f8552e4788b846c0d2b7f74743", async function bar() { return ; }); +Object.defineProperty($$RSC_SERVER_CACHE_0, "name", { + "value": "bar", + "writable": false +}); export var bar = registerServerReference($$RSC_SERVER_CACHE_0, "3128060c414d59f8552e4788b846c0d2b7f74743", null); diff --git a/test/e2e/app-dir/use-cache/app/form.tsx b/test/e2e/app-dir/use-cache/app/form.tsx new file mode 100644 index 0000000000000..1b0cb179b6106 --- /dev/null +++ b/test/e2e/app-dir/use-cache/app/form.tsx @@ -0,0 +1,39 @@ +'use client' + +import { useActionState } from 'react' + +export function Form({ + foo, + bar, + baz, +}: { + foo: () => Promise + bar: () => Promise + baz: () => Promise +}) { + const [result, dispatch] = useActionState< + [number, number, number], + 'submit' | 'reset' + >( + async (_state, event) => { + if (event === 'reset') { + return [0, 0, 0] + } + + return [await foo(), await bar(), await baz()] + }, + [0, 0, 0] + ) + + return ( +
dispatch('submit')}> + {' '} + +

+ {result[0]} {result[1]} {result[2]} +

+
+ ) +} diff --git a/test/e2e/app-dir/use-cache/app/imported-from-client/cached.ts b/test/e2e/app-dir/use-cache/app/imported-from-client/cached.ts index 873f0c8a62ab2..9f6b0f9db9e7a 100644 --- a/test/e2e/app-dir/use-cache/app/imported-from-client/cached.ts +++ b/test/e2e/app-dir/use-cache/app/imported-from-client/cached.ts @@ -1,15 +1,21 @@ 'use cache' -export async function bar() { +function getRandomValue() { const v = Math.random() console.log(v) return v } +export async function foo() { + return getRandomValue() +} + +export const bar = async function () { + return getRandomValue() +} + const baz = async () => { - const v = Math.random() - console.log(v) - return v + return getRandomValue() } export { baz } diff --git a/test/e2e/app-dir/use-cache/app/imported-from-client/page.tsx b/test/e2e/app-dir/use-cache/app/imported-from-client/page.tsx index 57cc34947221a..dc0a8c9ebd5aa 100644 --- a/test/e2e/app-dir/use-cache/app/imported-from-client/page.tsx +++ b/test/e2e/app-dir/use-cache/app/imported-from-client/page.tsx @@ -1,32 +1,8 @@ 'use client' -import { useActionState } from 'react' -import { bar, baz } from './cached' +import { foo, bar, baz } from './cached' +import { Form } from '../form' export default function Page() { - const [result, dispatch] = useActionState< - [number, number], - 'submit' | 'reset' - >( - async (_state, event) => { - if (event === 'reset') { - return [0, 0] - } - - return [await bar(), await baz()] - }, - [0, 0] - ) - - return ( -
dispatch('submit')}> - -

- {result[0]} {result[1]} -

- -
- ) + return
} diff --git a/test/e2e/app-dir/use-cache/app/passed-to-client/page.tsx b/test/e2e/app-dir/use-cache/app/passed-to-client/page.tsx new file mode 100644 index 0000000000000..1c4bfe9b97cbc --- /dev/null +++ b/test/e2e/app-dir/use-cache/app/passed-to-client/page.tsx @@ -0,0 +1,26 @@ +import { Form } from '../form' + +function getRandomValue() { + const v = Math.random() + console.log(v) + return v +} + +export default function Page() { + return ( + { + 'use cache' + return getRandomValue() + }} + /> + ) +} diff --git a/test/e2e/app-dir/use-cache/use-cache.test.ts b/test/e2e/app-dir/use-cache/use-cache.test.ts index 1fb655e29a4a5..d327d1e5e275f 100644 --- a/test/e2e/app-dir/use-cache/use-cache.test.ts +++ b/test/e2e/app-dir/use-cache/use-cache.test.ts @@ -133,23 +133,45 @@ describe('use-cache', () => { it('should cache results for cached funtions imported from client components', async () => { const browser = await next.browser('/imported-from-client') - expect(await browser.elementByCss('p').text()).toBe('0 0') + expect(await browser.elementByCss('p').text()).toBe('0 0 0') await browser.elementById('submit-button').click() - let twoRandomValues: string + let threeRandomValues: string await retry(async () => { - twoRandomValues = await browser.elementByCss('p').text() - expect(twoRandomValues).toMatch(/\d\.\d+ \d\.\d+/) + threeRandomValues = await browser.elementByCss('p').text() + expect(threeRandomValues).toMatch(/\d\.\d+ \d\.\d+/) }) await browser.elementById('reset-button').click() - expect(await browser.elementByCss('p').text()).toBe('0 0') + expect(await browser.elementByCss('p').text()).toBe('0 0 0') await browser.elementById('submit-button').click() await retry(async () => { - expect(await browser.elementByCss('p').text()).toBe(twoRandomValues) + expect(await browser.elementByCss('p').text()).toBe(threeRandomValues) + }) + }) + + it('should cache results for cached funtions passed client components', async () => { + const browser = await next.browser('/passed-to-client') + expect(await browser.elementByCss('p').text()).toBe('0 0 0') + await browser.elementById('submit-button').click() + + let threeRandomValues: string + + await retry(async () => { + threeRandomValues = await browser.elementByCss('p').text() + expect(threeRandomValues).toMatch(/\d\.\d+ \d\.\d+/) + }) + + await browser.elementById('reset-button').click() + expect(await browser.elementByCss('p').text()).toBe('0 0 0') + + await browser.elementById('submit-button').click() + + await retry(async () => { + expect(await browser.elementByCss('p').text()).toBe(threeRandomValues) }) })