Skip to content

Commit

Permalink
Update transform exports and tests (#45251)
Browse files Browse the repository at this point in the history
<!--
Thanks for opening a PR! Your contribution is much appreciated.
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change that you're making:
-->

## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see
[`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the
feature request has been accepted for implementation before opening a
PR.
- [ ] Related issues linked using `fixes #number`
- [ ]
[e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see
[`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm build && pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
  • Loading branch information
shuding committed Jan 25, 2023
1 parent 6a51edc commit ac0b6d2
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 41 deletions.
9 changes: 6 additions & 3 deletions packages/next-swc/crates/core/src/lib.rs
Expand Up @@ -239,7 +239,7 @@ where
config.clone(),
path,
cm,
comments,
comments.clone(),
),
)
})
Expand All @@ -261,8 +261,11 @@ where
None => Either::Right(noop()),
},
match &opts.server_actions {
Some(config) =>
Either::Left(server_actions::server_actions(&file.name, config.clone())),
Some(config) => Either::Left(server_actions::server_actions(
&file.name,
config.clone(),
comments,
)),
None => Either::Right(noop()),
},
)
Expand Down
91 changes: 58 additions & 33 deletions packages/next-swc/crates/core/src/server_actions.rs
@@ -1,11 +1,16 @@
use next_binding::swc::core::{
common::{errors::HANDLER, util::take::Take, FileName, DUMMY_SP},
common::{
comments::{Comment, CommentKind, Comments},
errors::HANDLER,
util::take::Take,
BytePos, FileName, DUMMY_SP,
},
ecma::{
ast::{
op, ArrayLit, AssignExpr, BlockStmt, CallExpr, ComputedPropName, Decl, ExportDecl,
Expr, ExprStmt, FnDecl, Function, Id, Ident, KeyValueProp, Lit, MemberExpr, MemberProp,
ModuleDecl, ModuleItem, PatOrExpr, Prop, PropName, ReturnStmt, Stmt, Str, VarDecl,
VarDeclKind, VarDeclarator,
Module, ModuleDecl, ModuleItem, PatOrExpr, Prop, PropName, ReturnStmt, Stmt, Str,
VarDecl, VarDeclKind, VarDeclarator,
},
atoms::JsWord,
utils::{find_pat_ids, private_ident, quote_ident, ExprFactory},
Expand All @@ -19,28 +24,40 @@ use serde::Deserialize;

#[derive(Clone, Debug, Deserialize)]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub struct Config {}
pub struct Config {
pub is_server: bool,
}

pub fn server_actions(file_name: &FileName, config: Config) -> impl VisitMut + Fold {
pub fn server_actions<C: Comments>(
file_name: &FileName,
config: Config,
comments: C,
) -> impl VisitMut + Fold {
as_folder(ServerActions {
config,
comments,
file_name: file_name.clone(),
start_pos: BytePos(0),
in_action_file: false,
in_export_decl: false,
has_action: false,
top_level: false,
closure_candidates: Default::default(),
annotations: Default::default(),
extra_items: Default::default(),
})
}

struct ServerActions {
struct ServerActions<C: Comments> {
#[allow(unused)]
config: Config,
file_name: FileName,
comments: C,

start_pos: BytePos,
in_action_file: bool,
in_export_decl: bool,
has_action: bool,
top_level: bool,

closure_candidates: Vec<Id>,
Expand All @@ -49,7 +66,7 @@ struct ServerActions {
extra_items: Vec<ModuleItem>,
}

impl VisitMut for ServerActions {
impl<C: Comments> VisitMut for ServerActions<C> {
fn visit_mut_export_decl(&mut self, decl: &mut ExportDecl) {
let old = self.in_export_decl;
self.in_export_decl = true;
Expand Down Expand Up @@ -97,6 +114,8 @@ impl VisitMut for ServerActions {
let action_name: JsWord = format!("$ACTION_{}", f.ident.sym).into();
let action_ident = private_ident!(action_name.clone());

self.has_action = true;

// myAction.$$typeof = Symbol.for('react.action.reference');
self.annotations.push(annotate(
&f.ident,
Expand Down Expand Up @@ -124,22 +143,24 @@ impl VisitMut for ServerActions {
.push(annotate(&f.ident, "$$name", action_name.into()));

if self.top_level {
// export const $ACTION_myAction = myAction;
self.extra_items
.push(ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
span: DUMMY_SP,
decl: Decl::Var(Box::new(VarDecl {
if !(self.in_action_file && self.in_export_decl) {
// export const $ACTION_myAction = myAction;
self.extra_items
.push(ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
span: DUMMY_SP,
kind: VarDeclKind::Const,
declare: Default::default(),
decls: vec![VarDeclarator {
decl: Decl::Var(Box::new(VarDecl {
span: DUMMY_SP,
name: action_ident.into(),
init: Some(f.ident.clone().into()),
definite: Default::default(),
}],
})),
})));
kind: VarDeclKind::Const,
declare: Default::default(),
decls: vec![VarDeclarator {
span: DUMMY_SP,
name: action_ident.into(),
init: Some(f.ident.clone().into()),
definite: Default::default(),
}],
})),
})));
}
} else {
// Hoist the function to the top level.

Expand Down Expand Up @@ -215,25 +236,17 @@ impl VisitMut for ServerActions {
}
}

fn visit_mut_module_item(&mut self, s: &mut ModuleItem) {
s.visit_mut_children_with(self);

if self.in_action_file {
if let ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
decl: decl @ Decl::Fn(..),
..
})) = s
{
*s = ModuleItem::Stmt(Stmt::Decl(decl.take()));
}
}
fn visit_mut_module(&mut self, m: &mut Module) {
self.start_pos = m.span.lo;
m.visit_mut_children_with(self);
}

fn visit_mut_module_items(&mut self, stmts: &mut Vec<ModuleItem>) {
if let Some(ModuleItem::Stmt(Stmt::Expr(first))) = stmts.first() {
match &*first.expr {
Expr::Lit(Lit::Str(Str { value, .. })) if value == "use action" => {
self.in_action_file = true;
self.has_action = true;
}
_ => {}
}
Expand All @@ -258,6 +271,18 @@ impl VisitMut for ServerActions {
*stmts = new;

self.annotations = old_annotations;

if self.has_action {
// Prepend a special comment to the top of the file.
self.comments.add_leading(
self.start_pos,
Comment {
span: DUMMY_SP,
kind: CommentKind::Block,
text: " __next_internal_action_entry_do_not_use__ ".into(),
},
);
}
}

fn visit_mut_stmts(&mut self, stmts: &mut Vec<Stmt>) {
Expand Down
3 changes: 2 additions & 1 deletion packages/next-swc/crates/core/tests/fixture.rs
Expand Up @@ -307,7 +307,8 @@ fn server_actions_fixture(input: PathBuf) {
&|_tr| {
server_actions(
&FileName::Real("/app/item.js".into()),
server_actions::Config {},
server_actions::Config { is_server: true },
_tr.comments.as_ref().clone(),
)
},
&input,
Expand Down
@@ -1,4 +1,4 @@
export function Item({ id1 , id2 }) {
/* __next_internal_action_entry_do_not_use__ */ export function Item({ id1 , id2 }) {
async function deleteItem() {
return $ACTION_deleteItem(deleteItem.$$closure);
}
Expand Down
@@ -1,4 +1,4 @@
async function myAction(a, b, c) {
/* __next_internal_action_entry_do_not_use__ */ async function myAction(a, b, c) {
console.log('a');
}
myAction.$$typeof = Symbol.for("react.action.reference");
Expand Down
@@ -1,8 +1,7 @@
// app/send.ts
async function myAction(a, b, c) {
/* __next_internal_action_entry_do_not_use__ */ export async function myAction(a, b, c) {
console.log('a');
}
myAction.$$typeof = Symbol.for("react.action.reference");
myAction.$$filepath = "/app/item.js";
myAction.$$name = "$ACTION_myAction";
export const $ACTION_myAction = myAction;

0 comments on commit ac0b6d2

Please sign in to comment.