Skip to content

Commit

Permalink
fix: Fix syntax context usage and add PURE comments in server actions (
Browse files Browse the repository at this point in the history
…#70014)

### What?

Fix usages of `SyntaxContext` in server actions transform.

### Why?

This is part of [the tree-shaking PR](#69344).

### How?
  • Loading branch information
kdy1 authored Sep 13, 2024
1 parent 21855f9 commit e40574b
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ impl ReactServerComponentValidator {
"useTransition",
"useOptimistic",
"useActionState",
"experimental_useOptimistic",
],
),
(
Expand Down
43 changes: 31 additions & 12 deletions crates/next-custom-transforms/src/transforms/server_actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use swc_core::{
comments::{Comment, CommentKind, Comments},
errors::HANDLER,
util::take::Take,
BytePos, FileName, Span, SyntaxContext, DUMMY_SP,
BytePos, FileName, Mark, Span, SyntaxContext, DUMMY_SP,
},
ecma::{
ast::*,
Expand Down Expand Up @@ -68,6 +68,8 @@ pub fn server_actions<C: Comments>(
annotations: Default::default(),
extra_items: Default::default(),
export_actions: Default::default(),

private_ctxt: SyntaxContext::empty().apply_mark(Mark::new()),
})
}

Expand Down Expand Up @@ -111,6 +113,8 @@ struct ServerActions<C: Comments> {
annotations: Vec<Stmt>,
extra_items: Vec<ModuleItem>,
export_actions: Vec<String>,

private_ctxt: SyntaxContext,
}

impl<C: Comments> ServerActions<C> {
Expand Down Expand Up @@ -160,7 +164,7 @@ impl<C: Comments> ServerActions<C> {
arrow: Option<&mut ArrowExpr>,
) -> Option<Box<Expr>> {
let action_name: JsWord = gen_ident(&mut self.reference_index);
let action_ident = private_ident!(action_name.clone());
let action_ident = Ident::new(action_name.clone(), DUMMY_SP, self.private_ctxt);
let export_name: JsWord = action_name;

self.has_action = true;
Expand All @@ -184,6 +188,7 @@ impl<C: Comments> ServerActions<C> {
if let BlockStmtOrExpr::BlockStmt(block) = &mut *a.body {
block.visit_mut_with(&mut ClosureReplacer {
used_ids: &ids_from_closure,
private_ctxt: self.private_ctxt,
});
}

Expand All @@ -207,7 +212,12 @@ impl<C: Comments> ServerActions<C> {
let mut pats = vec![];
for i in 0..ids_from_closure.len() {
pats.push(Some(Pat::Ident(
IdentName::new(format!("$$ACTION_ARG_{i}").into(), DUMMY_SP).into(),
Ident::new(
format!("$$ACTION_ARG_{i}").into(),
DUMMY_SP,
self.private_ctxt,
)
.into(),
)));
}
let decryption_decl = VarDecl {
Expand Down Expand Up @@ -316,6 +326,7 @@ impl<C: Comments> ServerActions<C> {

f.body.visit_mut_with(&mut ClosureReplacer {
used_ids: &ids_from_closure,
private_ctxt: self.private_ctxt,
});

// export async function $ACTION_myAction () {}
Expand All @@ -339,7 +350,12 @@ impl<C: Comments> ServerActions<C> {
let mut pats = vec![];
for i in 0..ids_from_closure.len() {
pats.push(Some(Pat::Ident(
IdentName::new(format!("$$ACTION_ARG_{i}").into(), DUMMY_SP).into(),
Ident::new(
format!("$$ACTION_ARG_{i}").into(),
DUMMY_SP,
self.private_ctxt,
)
.into(),
)));
}
let decryption_decl = VarDecl {
Expand Down Expand Up @@ -490,7 +506,7 @@ impl<C: Comments> VisitMut for ServerActions<C> {
match f.ident.as_mut() {
None => {
let action_name = gen_ident(&mut self.reference_index);
let ident = Ident::new(action_name, DUMMY_SP, Default::default());
let ident = Ident::new(action_name, DUMMY_SP, self.private_ctxt);
f.ident.insert(ident)
}
Some(i) => i,
Expand Down Expand Up @@ -860,7 +876,7 @@ impl<C: Comments> VisitMut for ServerActions<C> {
let new_ident = Ident::new(
gen_ident(&mut self.reference_index),
DUMMY_SP,
Default::default(),
self.private_ctxt,
);
f.ident = Some(new_ident.clone());
self.exported_idents
Expand All @@ -882,7 +898,7 @@ impl<C: Comments> VisitMut for ServerActions<C> {
let new_ident = Ident::new(
gen_ident(&mut self.reference_index),
DUMMY_SP,
Default::default(),
self.private_ctxt,
);

self.exported_idents
Expand All @@ -904,7 +920,7 @@ impl<C: Comments> VisitMut for ServerActions<C> {
let new_ident = Ident::new(
gen_ident(&mut self.reference_index),
DUMMY_SP,
Default::default(),
self.private_ctxt,
);

self.exported_idents
Expand Down Expand Up @@ -996,12 +1012,14 @@ impl<C: Comments> VisitMut for ServerActions<C> {
let action_id =
generate_action_id(&self.config.hash_salt, &self.file_name, export_name);

let span = Span::dummy_with_cmt();
self.comments.add_pure_comment(span.lo);
if export_name == "default" {
let export_expr = ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr(
ExportDefaultExpr {
span: DUMMY_SP,
expr: Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
span,
callee: Callee::Expr(Box::new(Expr::Ident(
create_ref_ident.clone(),
))),
Expand All @@ -1025,7 +1043,7 @@ impl<C: Comments> VisitMut for ServerActions<C> {
.into(),
),
init: Some(Box::new(Expr::Call(CallExpr {
span: DUMMY_SP,
span,
callee: Callee::Expr(Box::new(Expr::Ident(
create_ref_ident.clone(),
))),
Expand Down Expand Up @@ -1704,6 +1722,7 @@ fn collect_decl_idents_in_stmt(stmt: &Stmt, ids: &mut Vec<Id>) {

pub(crate) struct ClosureReplacer<'a> {
used_ids: &'a [Name],
private_ctxt: SyntaxContext,
}

impl ClosureReplacer<'_> {
Expand All @@ -1722,7 +1741,7 @@ impl VisitMut for ClosureReplacer<'_> {
// $$ACTION_ARG_0
format!("$$ACTION_ARG_{index}").into(),
DUMMY_SP,
Default::default(),
self.private_ctxt,
));
}
}
Expand All @@ -1739,7 +1758,7 @@ impl VisitMut for ClosureReplacer<'_> {
// $$ACTION_ARG_0
format!("$$ACTION_ARG_{index}").into(),
DUMMY_SP,
Default::default(),
self.private_ctxt,
))),
})));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,13 @@
: ^^^^^^^^^^^^^^^^^^^^
17 | } from 'react'
`----
x You're importing a component that needs `experimental_useOptimistic`. This React hook only works in a client component. To fix, mark the file (or its parent) with the `"use client"` directive.
|
| Learn more: https://nextjs.org/docs/app/building-your-application/rendering/client-components
|
|
,-[input.js:19:1]
18 |
19 | import { experimental_useOptimistic as useOptimistic } from 'react'
: ^^^^^^^^^^^^^^^^^^^^^^^^^^
`----
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// app/send.ts
/* __next_internal_action_entry_do_not_use__ {"c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default","e10665baac148856374b2789aceb970f66fec33e":"myAction"} */ export default createServerReference("c18c215a6b7cdc64bf709f3a714ffdef1bf9651d");
/* __next_internal_action_entry_do_not_use__ {"c18c215a6b7cdc64bf709f3a714ffdef1bf9651d":"default","e10665baac148856374b2789aceb970f66fec33e":"myAction"} */ export default /*#__PURE__*/ createServerReference("c18c215a6b7cdc64bf709f3a714ffdef1bf9651d");
import { createServerReference } from "private-next-rsc-action-client-wrapper";
export var myAction = createServerReference("e10665baac148856374b2789aceb970f66fec33e");
export var myAction = /*#__PURE__*/ createServerReference("e10665baac148856374b2789aceb970f66fec33e");
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// app/send.ts
/* __next_internal_action_entry_do_not_use__ {"ab21efdafbe611287bc25c0462b1e0510d13e48b":"foo"} */ export var foo = createServerReference("ab21efdafbe611287bc25c0462b1e0510d13e48b");
/* __next_internal_action_entry_do_not_use__ {"ab21efdafbe611287bc25c0462b1e0510d13e48b":"foo"} */ export var foo = /*#__PURE__*/ createServerReference("ab21efdafbe611287bc25c0462b1e0510d13e48b");
import { createServerReference } from "private-next-rsc-action-client-wrapper";

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
/* __next_internal_action_entry_do_not_use__ {"ac840dcaf5e8197cb02b7f3a43c119b7a770b272":"bar"} */ export var bar = createServerReference("ac840dcaf5e8197cb02b7f3a43c119b7a770b272");
/* __next_internal_action_entry_do_not_use__ {"ac840dcaf5e8197cb02b7f3a43c119b7a770b272":"bar"} */ export var bar = /*#__PURE__*/ createServerReference("ac840dcaf5e8197cb02b7f3a43c119b7a770b272");
import { createServerReference } from "private-next-rsc-action-client-wrapper";

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 26 additions & 1 deletion turbopack/crates/turbopack-ecmascript/src/swc_comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{cell::RefCell, collections::HashMap, mem::take};
use swc_core::{
base::SwcComments,
common::{
comments::{Comment, Comments},
comments::{Comment, CommentKind, Comments},
BytePos,
},
};
Expand Down Expand Up @@ -130,6 +130,31 @@ impl Comments for ImmutableComments {
panic!("Comments are immutable after parsing")
}

fn has_flag(&self, pos: BytePos, flag: &str) -> bool {
self.with_leading(pos, |cmts| {
for c in cmts {
if c.kind == CommentKind::Block {
for line in c.text.lines() {
// jsdoc
let line = line.trim_start_matches(['*', ' ']);
let line = line.trim();

//
if line.len() == (flag.len() + 5)
&& (line.starts_with("#__") || line.starts_with("@__"))
&& line.ends_with("__")
&& flag == &line[3..line.len() - 2]
{
return true;
}
}
}
}

false
})
}

fn with_leading<F, Ret>(&self, pos: BytePos, f: F) -> Ret
where
Self: Sized,
Expand Down

0 comments on commit e40574b

Please sign in to comment.