next-swc: Emit errors and add tests to next-ssg (#32254)
## Bug - [ ] Related issues linked using `fixes #number` - [ ] Integration tests added - [ ] Errors have helpful link attached, see `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` - [ ] Integration tests added - [ ] Documentation added - [ ] Telemetry added. In case of a feature if it's used or not. - [ ] Errors have helpful link attached, see `contributing.md` ## Documentation / Examples - [ ] Make sure the linting passes by running `yarn lint`
This commit is contained in:
parent
f221f8857d
commit
b0bd0eefc6
14 changed files with 111 additions and 29 deletions
|
@ -1,3 +1,4 @@
|
|||
use easy_error::{bail, Error};
|
||||
use fxhash::FxHashSet;
|
||||
use std::mem::take;
|
||||
use swc_common::pass::{Repeat, Repeated};
|
||||
|
@ -6,7 +7,7 @@ use swc_ecmascript::ast::*;
|
|||
use swc_ecmascript::utils::ident::IdentLike;
|
||||
use swc_ecmascript::visit::FoldWith;
|
||||
use swc_ecmascript::{
|
||||
utils::Id,
|
||||
utils::{Id, HANDLER},
|
||||
visit::{noop_fold_type, Fold},
|
||||
};
|
||||
|
||||
|
@ -43,7 +44,7 @@ struct State {
|
|||
}
|
||||
|
||||
impl State {
|
||||
fn is_data_identifier(&mut self, i: &Ident) -> bool {
|
||||
fn is_data_identifier(&mut self, i: &Ident) -> Result<bool, Error> {
|
||||
let ssg_exports = &[
|
||||
"getStaticProps",
|
||||
"getStaticPaths",
|
||||
|
@ -53,27 +54,39 @@ impl State {
|
|||
if ssg_exports.contains(&&*i.sym) {
|
||||
if &*i.sym == "getServerSideProps" {
|
||||
if self.is_prerenderer {
|
||||
panic!(
|
||||
"You can not use getStaticProps or getStaticPaths with \
|
||||
getServerSideProps. To use SSG, please remove getServerSideProps"
|
||||
)
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
i.span,
|
||||
"You can not use getStaticProps or getStaticPaths with \
|
||||
getServerSideProps. To use SSG, please remove getServerSideProps",
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
bail!("both ssg and ssr functions present");
|
||||
}
|
||||
|
||||
self.is_server_props = true;
|
||||
} else {
|
||||
if self.is_server_props {
|
||||
panic!(
|
||||
"You can not use getStaticProps or getStaticPaths with \
|
||||
getServerSideProps. To use SSG, please remove getServerSideProps"
|
||||
)
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(
|
||||
i.span,
|
||||
"You can not use getStaticProps or getStaticPaths with \
|
||||
getServerSideProps. To use SSG, please remove getServerSideProps",
|
||||
)
|
||||
.emit()
|
||||
});
|
||||
bail!("both ssg and ssr functions present");
|
||||
}
|
||||
|
||||
self.is_prerenderer = true;
|
||||
}
|
||||
|
||||
true
|
||||
Ok(true)
|
||||
} else {
|
||||
false
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +148,11 @@ impl Fold for Analyzer<'_> {
|
|||
|
||||
self.state.cur_declaring.insert(f.ident.to_id());
|
||||
|
||||
self.in_data_fn |= self.state.is_data_identifier(&f.ident);
|
||||
if let Ok(is_data_identifier) = self.state.is_data_identifier(&f.ident) {
|
||||
self.in_data_fn |= is_data_identifier;
|
||||
} else {
|
||||
return f;
|
||||
}
|
||||
tracing::trace!(
|
||||
"ssg: Handling `{}{:?}`; in_data_fn = {:?}",
|
||||
f.ident.sym,
|
||||
|
@ -194,8 +211,13 @@ impl Fold for Analyzer<'_> {
|
|||
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(e)) => match &e.decl {
|
||||
Decl::Fn(f) => {
|
||||
// Drop getStaticProps.
|
||||
if self.state.is_data_identifier(&f.ident) {
|
||||
return ModuleItem::Stmt(Stmt::Empty(EmptyStmt { span: DUMMY_SP }));
|
||||
if let Ok(is_data_identifier) = self.state.is_data_identifier(&f.ident)
|
||||
{
|
||||
if is_data_identifier {
|
||||
return ModuleItem::Stmt(Stmt::Empty(EmptyStmt { span: DUMMY_SP }));
|
||||
}
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,8 +261,12 @@ impl Fold for Analyzer<'_> {
|
|||
|
||||
match &v.name {
|
||||
Pat::Ident(name) => {
|
||||
if self.state.is_data_identifier(&name.id) {
|
||||
self.in_data_fn = true;
|
||||
if let Ok(is_data_identifier) = self.state.is_data_identifier(&name.id) {
|
||||
if is_data_identifier {
|
||||
self.in_data_fn = true;
|
||||
}
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -472,23 +498,35 @@ impl Fold for NextSsg {
|
|||
| ExportSpecifier::Named(ExportNamedSpecifier {
|
||||
exported: Some(exported),
|
||||
..
|
||||
}) => !self.state.is_data_identifier(&exported),
|
||||
ExportSpecifier::Named(s) => !self.state.is_data_identifier(&s.orig),
|
||||
}) => self
|
||||
.state
|
||||
.is_data_identifier(&exported)
|
||||
.map(|is_data_identifier| !is_data_identifier),
|
||||
ExportSpecifier::Named(s) => self
|
||||
.state
|
||||
.is_data_identifier(&s.orig)
|
||||
.map(|is_data_identifier| !is_data_identifier),
|
||||
};
|
||||
|
||||
if !preserve {
|
||||
tracing::trace!("Dropping a export specifier because it's a data identifier");
|
||||
match preserve {
|
||||
Ok(false) => {
|
||||
tracing::trace!(
|
||||
"Dropping a export specifier because it's a data identifier"
|
||||
);
|
||||
|
||||
match s {
|
||||
ExportSpecifier::Named(ExportNamedSpecifier { orig, .. }) => {
|
||||
self.state.should_run_again = true;
|
||||
self.state.refs_from_data_fn.insert(orig.to_id());
|
||||
match s {
|
||||
ExportSpecifier::Named(ExportNamedSpecifier { orig, .. }) => {
|
||||
self.state.should_run_again = true;
|
||||
self.state.refs_from_data_fn.insert(orig.to_id());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
preserve
|
||||
false
|
||||
}
|
||||
Ok(true) => true,
|
||||
Err(_) => false,
|
||||
}
|
||||
});
|
||||
|
||||
n
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use next_swc::{
|
||||
disallow_re_export_all_in_page::disallow_re_export_all_in_page, next_dynamic::next_dynamic,
|
||||
next_ssg::next_ssg,
|
||||
};
|
||||
use std::path::PathBuf;
|
||||
use swc_common::FileName;
|
||||
|
@ -42,3 +43,9 @@ fn next_dynamic_errors(input: PathBuf) {
|
|||
&output,
|
||||
);
|
||||
}
|
||||
|
||||
#[fixture("tests/errors/next-ssg/**/input.js")]
|
||||
fn next_ssg_errors(input: PathBuf) {
|
||||
let output = input.parent().unwrap().join("output.js");
|
||||
test_fixture_allowing_error(syntax(), &|_tr| next_ssg(), &input, &output);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
export async function getStaticPaths() {}
|
||||
export const getServerSideProps = function getServerSideProps() {}
|
|
@ -0,0 +1,3 @@
|
|||
export var __N_SSG = true;
|
||||
export const getServerSideProps = function getServerSideProps() {
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
error: You can not use getStaticProps or getStaticPaths with getServerSideProps. To use SSG, please remove getServerSideProps
|
||||
--> input.js:2:14
|
||||
|
|
||||
2 | export const getServerSideProps = function getServerSideProps() {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
const getStaticProps = async () => {}
|
||||
export { a as getServerSideProps }
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
error: You can not use getStaticProps or getStaticPaths with getServerSideProps. To use SSG, please remove getServerSideProps
|
||||
--> input.js:2:15
|
||||
|
|
||||
2 | export { a as getServerSideProps }
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
export { a as getServerSideProps } from './input'
|
||||
export { getStaticPaths } from 'a'
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
error: You can not use getStaticProps or getStaticPaths with getServerSideProps. To use SSG, please remove getServerSideProps
|
||||
--> input.js:2:10
|
||||
|
|
||||
2 | export { getStaticPaths } from 'a'
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { getStaticProps, getServerSideProps }
|
|
@ -0,0 +1,6 @@
|
|||
error: You can not use getStaticProps or getStaticPaths with getServerSideProps. To use SSG, please remove getServerSideProps
|
||||
--> input.js:1:26
|
||||
|
|
||||
1 | export { getStaticProps, getServerSideProps }
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
Loading…
Reference in a new issue