From 93afebd953f6677c4dcfa13772e7237d08e7bcd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Tue, 21 Dec 2021 11:06:20 +0100 Subject: [PATCH 1/4] Fix asexpression for babel and swc --- .../next-swc/crates/core/src/page_config.rs | 13 +++- .../next-swc/crates/core/tests/fixture.rs | 13 +++- .../amp-hybrid/{input.js => input.tsx} | 2 +- .../fixture/page-config/amp-hybrid/output.js | 2 +- .../amp-true-asexpression/input.tsx | 11 ++++ .../amp-true-asexpression/output.js | 1 + .../amp-true-type-annotation/input.tsx | 11 ++++ .../amp-true-type-annotation/output.js | 1 + .../amp-true/{input.js => input.tsx} | 6 +- .../fixture/page-config/amp-true/output.js | 2 +- .../build/babel/plugins/next-page-config.ts | 13 ++-- .../babel-plugin-next-page-config.test.ts | 62 +++++++++++++++++++ 12 files changed, 123 insertions(+), 14 deletions(-) rename packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/{input.js => input.tsx} (83%) create mode 100644 packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/input.tsx create mode 100644 packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/output.js create mode 100644 packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/input.tsx create mode 100644 packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/output.js rename packages/next-swc/crates/core/tests/fixture/page-config/amp-true/{input.js => input.tsx} (52%) create mode 100644 test/unit/babel-plugin-next-page-config.test.ts diff --git a/packages/next-swc/crates/core/src/page_config.rs b/packages/next-swc/crates/core/src/page_config.rs index cbdf7fdd2ea168f..661b42738788c63 100644 --- a/packages/next-swc/crates/core/src/page_config.rs +++ b/packages/next-swc/crates/core/src/page_config.rs @@ -82,7 +82,18 @@ impl Fold for PageConfig { } if is_config { - if let Some(expr) = &decl.init { + let init = match &decl.init { + Some(expr) => { + Some(if let Expr::TsAs(obj) = &**expr { + &obj.expr + } else { + expr + }) + } + None => None + }; + + if let Some(expr) = init { if let Expr::Object(obj) = &**expr { for prop in &obj.props { if let PropOrSpread::Prop(prop) = prop { diff --git a/packages/next-swc/crates/core/tests/fixture.rs b/packages/next-swc/crates/core/tests/fixture.rs index e43e4a48a9cf822..2af67c01551d731 100644 --- a/packages/next-swc/crates/core/tests/fixture.rs +++ b/packages/next-swc/crates/core/tests/fixture.rs @@ -12,7 +12,7 @@ use std::path::PathBuf; use swc_common::{chain, comments::SingleThreadedComments, FileName, Mark, Span, DUMMY_SP}; use swc_ecma_transforms_testing::{test, test_fixture}; use swc_ecmascript::{ - parser::{EsConfig, Syntax}, + parser::{TsConfig, EsConfig, Syntax}, transforms::{react::jsx, resolver}, }; use testing::fixture; @@ -24,6 +24,13 @@ fn syntax() -> Syntax { }) } +fn syntax_ts() -> Syntax { + Syntax::Typescript(TsConfig { + tsx: true, + ..Default::default() + }) +} + #[fixture("tests/fixture/amp/**/input.js")] fn amp_attributes_fixture(input: PathBuf) { let output = input.parent().unwrap().join("output.js"); @@ -129,10 +136,10 @@ impl swc_ecmascript::visit::VisitMut for DropSpan { } } -#[fixture("tests/fixture/page-config/**/input.js")] +#[fixture("tests/fixture/page-config/**/input.tsx")] fn page_config_fixture(input: PathBuf) { let output = input.parent().unwrap().join("output.js"); - test_fixture(syntax(), &|_tr| page_config_test(), &input, &output); + test_fixture(syntax_ts(), &|_tr| page_config_test(), &input, &output); } #[fixture("tests/fixture/remove-console/**/input.js")] diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/input.js b/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/input.tsx similarity index 83% rename from packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/input.js rename to packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/input.tsx index 161941f6a051f39..10ae2de5ffd6c98 100644 --- a/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/input.js +++ b/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/input.tsx @@ -4,4 +4,4 @@ function About(props) { return

My AMP About Page!

} -export default About \ No newline at end of file +export default About diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/output.js b/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/output.js index 25e72e99c3aaa92..d84d3616a021a9d 100644 --- a/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/output.js +++ b/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/output.js @@ -4,4 +4,4 @@ export const config = { function About(props) { return

My AMP About Page!

; } -export default About; \ No newline at end of file +export default About; diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/input.tsx b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/input.tsx new file mode 100644 index 000000000000000..c6597c2a61d4c2e --- /dev/null +++ b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/input.tsx @@ -0,0 +1,11 @@ +import type { PageConfig } from "next" + +export const config = { + amp: true, +} as PageConfig + +function About(props) { + return

My AMP About Page!

+} + +export default About diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/output.js b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/output.js new file mode 100644 index 000000000000000..efe7399420dfa5a --- /dev/null +++ b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/output.js @@ -0,0 +1 @@ +const __NEXT_DROP_CLIENT_FILE__ = "__NEXT_DROP_CLIENT_FILE__ mock_timestamp"; diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/input.tsx b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/input.tsx new file mode 100644 index 000000000000000..7b468a712ba3a26 --- /dev/null +++ b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/input.tsx @@ -0,0 +1,11 @@ +import type { PageConfig } from "next" + +export const config: PageConfig = { + amp: true, +} + +function About(props) { + return

My AMP About Page!

+} + +export default About diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/output.js b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/output.js new file mode 100644 index 000000000000000..efe7399420dfa5a --- /dev/null +++ b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/output.js @@ -0,0 +1 @@ +const __NEXT_DROP_CLIENT_FILE__ = "__NEXT_DROP_CLIENT_FILE__ mock_timestamp"; diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/input.js b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/input.tsx similarity index 52% rename from packages/next-swc/crates/core/tests/fixture/page-config/amp-true/input.js rename to packages/next-swc/crates/core/tests/fixture/page-config/amp-true/input.tsx index 969710c0b67f6dc..00477d57b19cc4c 100644 --- a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/input.js +++ b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/input.tsx @@ -1,7 +1,9 @@ -export const config = { amp: true } +export const config = { + amp: true, +} function About(props) { return

My AMP About Page!

} -export default About \ No newline at end of file +export default About diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/output.js b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/output.js index 464d1bd2c66aee8..efe7399420dfa5a 100644 --- a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/output.js +++ b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/output.js @@ -1 +1 @@ -const __NEXT_DROP_CLIENT_FILE__ = "__NEXT_DROP_CLIENT_FILE__ mock_timestamp"; \ No newline at end of file +const __NEXT_DROP_CLIENT_FILE__ = "__NEXT_DROP_CLIENT_FILE__ mock_timestamp"; diff --git a/packages/next/build/babel/plugins/next-page-config.ts b/packages/next/build/babel/plugins/next-page-config.ts index 2e4725f290c1b1d..3126ba6ccf533ff 100644 --- a/packages/next/build/babel/plugins/next-page-config.ts +++ b/packages/next/build/babel/plugins/next-page-config.ts @@ -144,10 +144,13 @@ export default function nextPageConfig({ continue } - if (!BabelTypes.isObjectExpression(declaration.init)) { - const got = declaration.init - ? declaration.init.type - : 'undefined' + let { init } = declaration + if (BabelTypes.isTSAsExpression(init)) { + init = init.expression + } + + if (!BabelTypes.isObjectExpression(init)) { + const got = init ? init.type : 'undefined' throw new Error( errorMessage( exportState, @@ -156,7 +159,7 @@ export default function nextPageConfig({ ) } - for (const prop of declaration.init.properties) { + for (const prop of init.properties) { if (BabelTypes.isSpreadElement(prop)) { throw new Error( errorMessage( diff --git a/test/unit/babel-plugin-next-page-config.test.ts b/test/unit/babel-plugin-next-page-config.test.ts new file mode 100644 index 000000000000000..21609e2d81b4533 --- /dev/null +++ b/test/unit/babel-plugin-next-page-config.test.ts @@ -0,0 +1,62 @@ +/* eslint-env jest */ +import { transformSync } from '@babel/core' + +const babel = (code) => + transformSync(code, { + filename: 'page.tsx', + presets: ['@babel/preset-typescript'], + plugins: [require('next/dist/build/babel/plugins/next-page-config')], + babelrc: false, + configFile: false, + sourceType: 'module', + compact: true, + caller: { + name: 'tests', + isDev: false, + }, + } as any).code + +describe('babel plugin (next-page-config)', () => { + test('export config with type annotation', () => { + const output = babel('export const config: PageConfig = {};') + + expect(output).toMatch(`export const config={};`) + }) + + test('export config with AsExpression', () => { + const output = babel('export const config = {} as PageConfig;') + + expect(output).toMatch('export const config={};') + }) + + test('amp enabled', () => { + jest.spyOn(Date, 'now').mockReturnValue(1234) + const output = babel(` + export const config = { amp: true } + + function About(props) { + return

My AMP About Page!

+ } + + export default About`) + + expect(output).toMatch( + 'const __NEXT_DROP_CLIENT_FILE__="__NEXT_DROP_CLIENT_FILE__ 1234";' + ) + }) + + test('amp hybrid enabled', () => { + const output = babel(` + export const config = { amp: 'hybrid' } + + function About(props) { + return

My AMP About Page!

+ } + + export default About`) + + expect(output).toMatch( + "export const config={amp:'hybrid'};function About(props){return

My AMP About Page!

;}export default About;" + ) + }) +}) From cee2c1b404ebdf83be2bdaf2b8904d59971041b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Tue, 21 Dec 2021 17:02:40 +0100 Subject: [PATCH 2/4] match -> .map() --- packages/next-swc/crates/core/src/page_config.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/next-swc/crates/core/src/page_config.rs b/packages/next-swc/crates/core/src/page_config.rs index 661b42738788c63..da1763dad421b9b 100644 --- a/packages/next-swc/crates/core/src/page_config.rs +++ b/packages/next-swc/crates/core/src/page_config.rs @@ -82,16 +82,13 @@ impl Fold for PageConfig { } if is_config { - let init = match &decl.init { - Some(expr) => { - Some(if let Expr::TsAs(obj) = &**expr { - &obj.expr - } else { - expr - }) + let init = decl.init.as_ref().map(|expr| { + if let Expr::TsAs(ts_as) = &**expr { + &ts_as.expr + } else { + expr } - None => None - }; + }); if let Some(expr) = init { if let Expr::Object(obj) = &**expr { From 3882c693a28b308397ebad88a0d99c762d74d185 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Thu, 20 Jan 2022 10:04:32 +0100 Subject: [PATCH 3/4] Revert next-swc changes --- packages/next-swc/crates/core/src/page_config.rs | 10 +--------- packages/next-swc/crates/core/tests/fixture.rs | 13 +++---------- .../page-config/amp-hybrid/{input.tsx => input.js} | 2 +- .../tests/fixture/page-config/amp-hybrid/output.js | 2 +- .../page-config/amp-true-asexpression/input.tsx | 11 ----------- .../page-config/amp-true-asexpression/output.js | 1 - .../page-config/amp-true-type-annotation/input.tsx | 11 ----------- .../page-config/amp-true-type-annotation/output.js | 1 - .../page-config/amp-true/{input.tsx => input.js} | 6 ++---- .../tests/fixture/page-config/amp-true/output.js | 2 +- 10 files changed, 9 insertions(+), 50 deletions(-) rename packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/{input.tsx => input.js} (83%) delete mode 100644 packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/input.tsx delete mode 100644 packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/output.js delete mode 100644 packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/input.tsx delete mode 100644 packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/output.js rename packages/next-swc/crates/core/tests/fixture/page-config/amp-true/{input.tsx => input.js} (52%) diff --git a/packages/next-swc/crates/core/src/page_config.rs b/packages/next-swc/crates/core/src/page_config.rs index 065ef0a6ee2c208..0b214038a15f1ae 100644 --- a/packages/next-swc/crates/core/src/page_config.rs +++ b/packages/next-swc/crates/core/src/page_config.rs @@ -82,15 +82,7 @@ impl Fold for PageConfig { } if is_config { - let init = decl.init.as_ref().map(|expr| { - if let Expr::TsAs(ts_as) = &**expr { - &ts_as.expr - } else { - expr - } - }); - - if let Some(expr) = init { + if let Some(expr) = &decl.init { if let Expr::Object(obj) = &**expr { for prop in &obj.props { if let PropOrSpread::Prop(prop) = prop { diff --git a/packages/next-swc/crates/core/tests/fixture.rs b/packages/next-swc/crates/core/tests/fixture.rs index d3d9fec501cd60a..f575c26c3d8c4e4 100644 --- a/packages/next-swc/crates/core/tests/fixture.rs +++ b/packages/next-swc/crates/core/tests/fixture.rs @@ -12,7 +12,7 @@ use std::path::PathBuf; use swc_common::{chain, comments::SingleThreadedComments, FileName, Mark, Span, DUMMY_SP}; use swc_ecma_transforms_testing::{test, test_fixture}; use swc_ecmascript::{ - parser::{TsConfig, EsConfig, Syntax}, + parser::{EsConfig, Syntax}, transforms::{react::jsx, resolver}, }; use testing::fixture; @@ -24,13 +24,6 @@ fn syntax() -> Syntax { }) } -fn syntax_ts() -> Syntax { - Syntax::Typescript(TsConfig { - tsx: true, - ..Default::default() - }) -} - #[fixture("tests/fixture/amp/**/input.js")] fn amp_attributes_fixture(input: PathBuf) { let output = input.parent().unwrap().join("output.js"); @@ -150,10 +143,10 @@ impl swc_ecmascript::visit::VisitMut for DropSpan { } } -#[fixture("tests/fixture/page-config/**/input.tsx")] +#[fixture("tests/fixture/page-config/**/input.js")] fn page_config_fixture(input: PathBuf) { let output = input.parent().unwrap().join("output.js"); - test_fixture(syntax_ts(), &|_tr| page_config_test(), &input, &output); + test_fixture(syntax(), &|_tr| page_config_test(), &input, &output); } #[fixture("tests/fixture/remove-console/**/input.js")] diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/input.tsx b/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/input.js similarity index 83% rename from packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/input.tsx rename to packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/input.js index 10ae2de5ffd6c98..161941f6a051f39 100644 --- a/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/input.tsx +++ b/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/input.js @@ -4,4 +4,4 @@ function About(props) { return

My AMP About Page!

} -export default About +export default About \ No newline at end of file diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/output.js b/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/output.js index d84d3616a021a9d..25e72e99c3aaa92 100644 --- a/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/output.js +++ b/packages/next-swc/crates/core/tests/fixture/page-config/amp-hybrid/output.js @@ -4,4 +4,4 @@ export const config = { function About(props) { return

My AMP About Page!

; } -export default About; +export default About; \ No newline at end of file diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/input.tsx b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/input.tsx deleted file mode 100644 index c6597c2a61d4c2e..000000000000000 --- a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/input.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import type { PageConfig } from "next" - -export const config = { - amp: true, -} as PageConfig - -function About(props) { - return

My AMP About Page!

-} - -export default About diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/output.js b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/output.js deleted file mode 100644 index efe7399420dfa5a..000000000000000 --- a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-asexpression/output.js +++ /dev/null @@ -1 +0,0 @@ -const __NEXT_DROP_CLIENT_FILE__ = "__NEXT_DROP_CLIENT_FILE__ mock_timestamp"; diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/input.tsx b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/input.tsx deleted file mode 100644 index 7b468a712ba3a26..000000000000000 --- a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/input.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import type { PageConfig } from "next" - -export const config: PageConfig = { - amp: true, -} - -function About(props) { - return

My AMP About Page!

-} - -export default About diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/output.js b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/output.js deleted file mode 100644 index efe7399420dfa5a..000000000000000 --- a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true-type-annotation/output.js +++ /dev/null @@ -1 +0,0 @@ -const __NEXT_DROP_CLIENT_FILE__ = "__NEXT_DROP_CLIENT_FILE__ mock_timestamp"; diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/input.tsx b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/input.js similarity index 52% rename from packages/next-swc/crates/core/tests/fixture/page-config/amp-true/input.tsx rename to packages/next-swc/crates/core/tests/fixture/page-config/amp-true/input.js index 00477d57b19cc4c..969710c0b67f6dc 100644 --- a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/input.tsx +++ b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/input.js @@ -1,9 +1,7 @@ -export const config = { - amp: true, -} +export const config = { amp: true } function About(props) { return

My AMP About Page!

} -export default About +export default About \ No newline at end of file diff --git a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/output.js b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/output.js index efe7399420dfa5a..464d1bd2c66aee8 100644 --- a/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/output.js +++ b/packages/next-swc/crates/core/tests/fixture/page-config/amp-true/output.js @@ -1 +1 @@ -const __NEXT_DROP_CLIENT_FILE__ = "__NEXT_DROP_CLIENT_FILE__ mock_timestamp"; +const __NEXT_DROP_CLIENT_FILE__ = "__NEXT_DROP_CLIENT_FILE__ mock_timestamp"; \ No newline at end of file From c3d28048987dd00ab041a79ffe98faaa11424183 Mon Sep 17 00:00:00 2001 From: JJ Kasper Date: Sat, 5 Feb 2022 14:38:14 -0600 Subject: [PATCH 4/4] Add integration test --- .../typescript-basic/app/pages/page-config.tsx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 test/production/typescript-basic/app/pages/page-config.tsx diff --git a/test/production/typescript-basic/app/pages/page-config.tsx b/test/production/typescript-basic/app/pages/page-config.tsx new file mode 100644 index 000000000000000..1f3e7c5d6c4da76 --- /dev/null +++ b/test/production/typescript-basic/app/pages/page-config.tsx @@ -0,0 +1,17 @@ +import Link from 'next/link' +import { PageConfig } from 'next' + +export const config: PageConfig = { + unstable_runtimeJS: false, +} + +export default function Page() { + return ( + <> +

hello world

+ + to /another + + + ) +}