From b6d961e872bf593254655be320d91796c1624629 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Mon, 5 Aug 2024 14:04:51 +0200 Subject: [PATCH] Update `swc_core` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes GH-49. Co-authored-by: Donny/강동윤 --- Cargo.toml | 2 +- src/hast_util_to_swc.rs | 150 +++++++++++++++++++--------- src/lib.rs | 17 +++- src/mdx_plugin_recma_document.rs | 42 ++++---- src/mdx_plugin_recma_jsx_rewrite.rs | 65 ++++++++---- src/swc.rs | 6 +- src/swc_util_build_jsx.rs | 38 +++---- src/swc_utils.rs | 44 ++++---- tests/test.rs | 8 +- 9 files changed, 243 insertions(+), 129 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d18fd4d..88c6c3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ serializable = ["serde"] [dependencies] markdown = "1.0.0-alpha.18" serde = { version = "1", optional = true } -swc_core = { version = "0.96.0", features = [ +swc_core = { version = "0.100", features = [ "ecma_ast", "ecma_visit", "ecma_codegen", diff --git a/src/hast_util_to_swc.rs b/src/hast_util_to_swc.rs index 3e1e69b..47ec646 100644 --- a/src/hast_util_to_swc.rs +++ b/src/hast_util_to_swc.rs @@ -34,14 +34,14 @@ use crate::swc_utils::{ }; use core::str; use markdown::{Location, MdxExpressionKind}; +use swc_core::alloc::collections::FxHashSet; +use swc_core::common::Span; use swc_core::ecma::ast::{ Expr, ExprStmt, JSXAttr, JSXAttrOrSpread, JSXAttrValue, JSXClosingElement, JSXClosingFragment, JSXElement, JSXElementChild, JSXEmptyExpr, JSXExpr, JSXExprContainer, JSXFragment, JSXOpeningElement, JSXOpeningFragment, Lit, Module, ModuleItem, SpreadElement, Stmt, Str, }; -pub const MAGIC_EXPLICIT_MARKER: u32 = 1337; - /// Result. #[derive(Debug, PartialEq, Eq)] pub struct Program { @@ -82,6 +82,7 @@ pub fn hast_util_to_swc( tree: &hast::Node, path: Option, location: Option<&Location>, + explicit_jsxs: &mut FxHashSet, ) -> Result { let mut context = Context { space: Space::Html, @@ -89,7 +90,7 @@ pub fn hast_util_to_swc( esm: vec![], location, }; - let expr = match one(&mut context, tree)? { + let expr = match one(&mut context, tree, explicit_jsxs)? { Some(JSXElementChild::JSXFragment(x)) => Some(Expr::JSXFragment(x)), Some(JSXElementChild::JSXElement(x)) => Some(Expr::JSXElement(x)), Some(child) => Some(Expr::JSXFragment(create_fragment(vec![child], tree))), @@ -122,14 +123,15 @@ pub fn hast_util_to_swc( fn one( context: &mut Context, node: &hast::Node, + explicit_jsxs: &mut FxHashSet, ) -> Result, markdown::message::Message> { let value = match node { hast::Node::Comment(x) => Some(transform_comment(context, node, x)), - hast::Node::Element(x) => transform_element(context, node, x)?, - hast::Node::MdxJsxElement(x) => transform_mdx_jsx_element(context, node, x)?, + hast::Node::Element(x) => transform_element(context, node, x, explicit_jsxs)?, + hast::Node::MdxJsxElement(x) => transform_mdx_jsx_element(context, node, x, explicit_jsxs)?, hast::Node::MdxExpression(x) => transform_mdx_expression(context, node, x)?, hast::Node::MdxjsEsm(x) => transform_mdxjs_esm(context, node, x)?, - hast::Node::Root(x) => transform_root(context, node, x)?, + hast::Node::Root(x) => transform_root(context, node, x, explicit_jsxs)?, hast::Node::Text(x) => transform_text(context, node, x), // Ignore: hast::Node::Doctype(_) => None, @@ -141,6 +143,7 @@ fn one( fn all( context: &mut Context, parent: &hast::Node, + explicit_jsxs: &mut FxHashSet, ) -> Result, markdown::message::Message> { let mut result = vec![]; if let Some(children) = parent.children() { @@ -149,7 +152,7 @@ fn all( let child = &children[index]; // To do: remove line endings between table elements? // - if let Some(child) = one(context, child)? { + if let Some(child) = one(context, child, explicit_jsxs)? { result.push(child); } index += 1; @@ -188,6 +191,7 @@ fn transform_element( context: &mut Context, node: &hast::Node, element: &hast::Element, + explicit_jsxs: &mut FxHashSet, ) -> Result, markdown::message::Message> { let space = context.space; @@ -195,7 +199,7 @@ fn transform_element( context.space = Space::Svg; } - let children = all(context, node)?; + let children = all(context, node, explicit_jsxs)?; context.space = space; @@ -252,7 +256,6 @@ fn transform_element( attrs, children, node, - false, ))))) } @@ -261,6 +264,7 @@ fn transform_mdx_jsx_element( context: &mut Context, node: &hast::Node, element: &hast::MdxJsxElement, + explicit_jsxs: &mut FxHashSet, ) -> Result, markdown::message::Message> { let space = context.space; @@ -270,7 +274,7 @@ fn transform_mdx_jsx_element( } } - let children = all(context, node)?; + let children = all(context, node, explicit_jsxs)?; context.space = space; @@ -330,7 +334,8 @@ fn transform_mdx_jsx_element( } Ok(Some(if let Some(name) = &element.name { - JSXElementChild::JSXElement(Box::new(create_element(name, attrs, children, node, true))) + explicit_jsxs.insert(position_to_span(node.position())); + JSXElementChild::JSXElement(Box::new(create_element(name, attrs, children, node))) } else { JSXElementChild::JSXFragment(create_fragment(children, node)) })) @@ -377,8 +382,9 @@ fn transform_root( context: &mut Context, node: &hast::Node, _root: &hast::Root, + explicit_jsxs: &mut FxHashSet, ) -> Result, markdown::message::Message> { - let mut children = all(context, node)?; + let mut children = all(context, node, explicit_jsxs)?; let mut queue = vec![]; let mut nodes = vec![]; let mut seen = false; @@ -445,15 +451,8 @@ fn create_element( attrs: Vec, children: Vec, node: &hast::Node, - explicit: bool, ) -> JSXElement { - let mut span = position_to_span(node.position()); - - span.ctxt = if explicit { - swc_core::common::SyntaxContext::from_u32(MAGIC_EXPLICIT_MARKER) - } else { - swc_core::common::SyntaxContext::empty() - }; + let span = position_to_span(node.position()); JSXElement { opening: JSXOpeningElement { @@ -678,13 +677,16 @@ mod tests { use crate::markdown::mdast; use crate::swc::serialize; use pretty_assertions::assert_eq; + use swc_core::common::SyntaxContext; use swc_core::ecma::ast::{ - Ident, ImportDecl, ImportDefaultSpecifier, ImportPhase, ImportSpecifier, JSXAttrName, - JSXElementName, ModuleDecl, + Ident, IdentName, ImportDecl, ImportDefaultSpecifier, ImportPhase, ImportSpecifier, + JSXAttrName, JSXElementName, ModuleDecl, }; #[test] fn comments() -> Result<(), markdown::message::Message> { + let mut explicit_jsxs = FxHashSet::default(); + let mut comment_ast = hast_util_to_swc( &hast::Node::Comment(hast::Comment { value: "a".into(), @@ -692,6 +694,7 @@ mod tests { }), None, None, + &mut explicit_jsxs, )?; assert_eq!( @@ -741,6 +744,8 @@ mod tests { #[test] fn elements() -> Result<(), markdown::message::Message> { + let mut explicit_jsxs = FxHashSet::default(); + let mut element_ast = hast_util_to_swc( &hast::Node::Element(hast::Element { tag_name: "a".into(), @@ -753,6 +758,7 @@ mod tests { }), None, None, + &mut explicit_jsxs, )?; assert_eq!( @@ -768,12 +774,12 @@ mod tests { span: swc_core::common::DUMMY_SP, sym: "a".into(), optional: false, + ctxt: SyntaxContext::empty() }), attrs: vec![JSXAttrOrSpread::JSXAttr(JSXAttr { - name: JSXAttrName::Ident(Ident { + name: JSXAttrName::Ident(IdentName { sym: "className".into(), span: swc_core::common::DUMMY_SP, - optional: false, }), value: Some(JSXAttrValue::Lit(Lit::Str(Str { value: "b".into(), @@ -818,10 +824,11 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs, )? .module, - None + None, ), "{\"a\"};\n", "should support an `Element` w/ children", @@ -837,7 +844,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs, )? .module, None @@ -851,6 +859,8 @@ mod tests { #[test] fn element_attributes() -> Result<(), markdown::message::Message> { + let mut explicit_jsxs = FxHashSet::default(); + assert_eq!( serialize( &mut hast_util_to_swc( @@ -861,7 +871,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs, )? .module, None @@ -880,7 +891,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs, )? .module, None @@ -899,7 +911,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs, )? .module, None @@ -921,7 +934,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, None @@ -946,7 +960,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, None @@ -969,7 +984,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, None @@ -983,6 +999,8 @@ mod tests { #[test] fn mdx_element() -> Result<(), markdown::message::Message> { + let mut explicit_jsxs = FxHashSet::default(); + let mut mdx_element_ast = hast_util_to_swc( &hast::Node::MdxJsxElement(hast::MdxJsxElement { name: None, @@ -992,6 +1010,7 @@ mod tests { }), None, None, + &mut explicit_jsxs, )?; assert_eq!( @@ -1036,7 +1055,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, None @@ -1057,7 +1077,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, None @@ -1071,6 +1092,8 @@ mod tests { #[test] fn mdx_element_name() -> Result<(), markdown::message::Message> { + let mut explicit_jsxs = FxHashSet::default(); + assert_eq!( serialize( &mut hast_util_to_swc( @@ -1081,7 +1104,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, None @@ -1100,7 +1124,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, None @@ -1119,7 +1144,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, None @@ -1133,6 +1159,8 @@ mod tests { #[test] fn mdx_element_attributes() -> Result<(), markdown::message::Message> { + let mut explicit_jsxs = FxHashSet::default(); + assert_eq!( serialize( &mut hast_util_to_swc( @@ -1146,7 +1174,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, None @@ -1168,7 +1197,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, None @@ -1190,7 +1220,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, None @@ -1217,7 +1248,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, None @@ -1243,7 +1275,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs ) .err() .unwrap() @@ -1265,10 +1298,11 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs )? .module, - None + None, ), ";\n", "should support an `MdxElement` (element, expression attribute)", @@ -1283,7 +1317,8 @@ mod tests { position: None, }), None, - None + None, + &mut explicit_jsxs ).err().unwrap().to_string(), "Unexpected extra content in spread (such as `{...x,y}`): only a single spread is supported (such as `{...x}`) (mdxjs-rs:swc)", "should support an `MdxElement` (element, broken expression attribute)", @@ -1294,6 +1329,8 @@ mod tests { #[test] fn mdx_expression() -> Result<(), markdown::message::Message> { + let mut explicit_jsxs = FxHashSet::default(); + let mut mdx_expression_ast = hast_util_to_swc( &hast::Node::MdxExpression(hast::MdxExpression { value: "a".into(), @@ -1302,6 +1339,7 @@ mod tests { }), None, None, + &mut explicit_jsxs, )?; assert_eq!( @@ -1323,6 +1361,7 @@ mod tests { sym: "a".into(), span: swc_core::common::DUMMY_SP, optional: false, + ctxt: SyntaxContext::empty() }))), span: swc_core::common::DUMMY_SP, },)], @@ -1351,6 +1390,8 @@ mod tests { #[test] fn mdx_esm() -> Result<(), markdown::message::Message> { + let mut explicit_jsxs = FxHashSet::default(); + let mut mdxjs_esm_ast = hast_util_to_swc( &hast::Node::MdxjsEsm(hast::MdxjsEsm { value: "import a from 'b'".into(), @@ -1359,6 +1400,7 @@ mod tests { }), None, None, + &mut explicit_jsxs, )?; assert_eq!( @@ -1373,6 +1415,7 @@ mod tests { sym: "a".into(), optional: false, span: swc_core::common::DUMMY_SP, + ctxt: SyntaxContext::empty() }, span: swc_core::common::DUMMY_SP, })], @@ -1407,7 +1450,8 @@ mod tests { stops: vec![], }), None, - None + None, + &mut explicit_jsxs ) .err() .unwrap() @@ -1421,6 +1465,8 @@ mod tests { #[test] fn root() -> Result<(), markdown::message::Message> { + let mut explicit_jsxs = FxHashSet::default(); + let mut root_ast = hast_util_to_swc( &hast::Node::Root(hast::Root { children: vec![hast::Node::Text(hast::Text { @@ -1431,6 +1477,7 @@ mod tests { }), None, None, + &mut explicit_jsxs, )?; assert_eq!( @@ -1477,6 +1524,8 @@ mod tests { #[test] fn text() -> Result<(), markdown::message::Message> { + let mut explicit_jsxs = FxHashSet::default(); + let mut text_ast = hast_util_to_swc( &hast::Node::Text(hast::Text { value: "a".into(), @@ -1484,6 +1533,7 @@ mod tests { }), None, None, + &mut explicit_jsxs, )?; assert_eq!( @@ -1530,6 +1580,8 @@ mod tests { #[test] fn text_empty() -> Result<(), markdown::message::Message> { + let mut explicit_jsxs = FxHashSet::default(); + let text_ast = hast_util_to_swc( &hast::Node::Text(hast::Text { value: String::new(), @@ -1537,6 +1589,7 @@ mod tests { }), None, None, + &mut explicit_jsxs, )?; assert_eq!( @@ -1558,10 +1611,13 @@ mod tests { #[test] fn doctype() -> Result<(), markdown::message::Message> { + let mut explicit_jsxs = FxHashSet::default(); + let mut doctype_ast = hast_util_to_swc( &hast::Node::Doctype(hast::Doctype { position: None }), None, None, + &mut explicit_jsxs, )?; assert_eq!( diff --git a/src/lib.rs b/src/lib.rs index a6dd8a4..b8ca572 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,6 +31,7 @@ use crate::{ swc_util_build_jsx::{swc_util_build_jsx, Options as BuildOptions}, }; use markdown::{message, to_mdast, Constructs, Location, ParseOptions}; +use swc_core::alloc::collections::FxHashSet; pub use crate::configuration::{MdxConstructs, MdxParseOptions, Options}; pub use crate::mdx_plugin_recma_document::JsxRuntime; @@ -110,12 +111,24 @@ pub fn compile(value: &str, options: &Options) -> Result { replacements.push(create_layout_decl(Expr::Class(cls))); @@ -217,7 +218,7 @@ pub fn mdx_plugin_recma_document( bytepos_to_point(expr.span.lo, location).as_ref(), )?; layout = true; - layout_position = span_to_position(&expr.span, location); + layout_position = span_to_position(expr.span, location); replacements.push(create_layout_decl(*expr.expr)); } // ```js @@ -248,7 +249,7 @@ pub fn mdx_plugin_recma_document( bytepos_to_point(ident.span.lo, location).as_ref(), )?; layout = true; - layout_position = span_to_position(&ident.span, location); + layout_position = span_to_position(ident.span, location); take = true; id = Some(ident.clone()); } @@ -278,7 +279,7 @@ pub fn mdx_plugin_recma_document( if let Some(source) = source { replacements.push(ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { specifiers: vec![ImportSpecifier::Named(ImportNamedSpecifier { - local: create_ident("MDXLayout"), + local: create_ident("MDXLayout").into(), imported: Some(ModuleExportName::Ident(id)), span: swc_core::common::DUMMY_SP, is_type_only: false, @@ -386,7 +387,7 @@ fn create_mdx_content(expr: Option, has_internal_layout: bool) -> Vec, has_internal_layout: bool) -> Vec, has_internal_layout: bool) -> Vec, has_internal_layout: bool) -> Vec, has_internal_layout: bool) -> Vec, has_internal_layout: bool) -> Vec, has_internal_layout: bool) -> Vec ModuleItem { declare: false, decls: vec![VarDeclarator { name: Pat::Ident(BindingIdent { - id: create_ident("MDXLayout"), + id: create_ident("MDXLayout").into(), type_ann: None, }), init: Some(Box::new(expr)), @@ -529,6 +534,7 @@ fn create_layout_decl(expr: Expr) -> ModuleItem { definite: false, }], span: swc_core::common::DUMMY_SP, + ctxt: SyntaxContext::empty(), })))) } @@ -563,6 +569,7 @@ mod tests { use crate::swc_utils::create_bool_expression; use markdown::{to_mdast, ParseOptions}; use pretty_assertions::assert_eq; + use swc_core::alloc::collections::FxHashSet; use swc_core::ecma::ast::{ EmptyStmt, ExportDefaultDecl, ExprStmt, JSXClosingFragment, JSXFragment, JSXOpeningFragment, JSXText, Module, TsInterfaceBody, TsInterfaceDecl, WhileStmt, @@ -579,7 +586,8 @@ mod tests { }, )?; let hast = mdast_util_to_hast(&mdast); - let mut program = hast_util_to_swc(&hast, None, Some(&location))?; + let mut program = + hast_util_to_swc(&hast, None, Some(&location), &mut FxHashSet::default())?; mdx_plugin_recma_document(&mut program, &DocumentOptions::default(), Some(&location))?; Ok(serialize(&mut program.module, Some(&program.comments))) } @@ -837,7 +845,7 @@ export default MDXContent; decl: DefaultDecl::TsInterfaceDecl(Box::new( TsInterfaceDecl { span: swc_core::common::DUMMY_SP, - id: create_ident("a"), + id: create_ident("a").into(), declare: true, type_params: None, extends: vec![], @@ -992,14 +1000,14 @@ export default MDXContent; expr: Box::new(Expr::JSXElement(Box::new(JSXElement { span: swc_core::common::DUMMY_SP, opening: JSXOpeningElement { - name: JSXElementName::Ident(create_ident("a")), + name: JSXElementName::Ident(create_ident("a").into()), attrs: vec![], self_closing: false, type_args: None, span: swc_core::common::DUMMY_SP, }, closing: Some(JSXClosingElement { - name: JSXElementName::Ident(create_ident("a")), + name: JSXElementName::Ident(create_ident("a").into()), span: swc_core::common::DUMMY_SP, }), children: vec![JSXElementChild::JSXText(JSXText { diff --git a/src/mdx_plugin_recma_jsx_rewrite.rs b/src/mdx_plugin_recma_jsx_rewrite.rs index 8568f1b..5140297 100644 --- a/src/mdx_plugin_recma_jsx_rewrite.rs +++ b/src/mdx_plugin_recma_jsx_rewrite.rs @@ -3,7 +3,7 @@ //! Port of , //! by the same author. -use crate::hast_util_to_swc::{Program, MAGIC_EXPLICIT_MARKER}; +use crate::hast_util_to_swc::Program; use crate::swc_utils::{ create_binary_expression, create_bool_expression, create_call_expression, create_ident, create_ident_expression, create_jsx_name_from_str, create_member, @@ -12,6 +12,8 @@ use crate::swc_utils::{ jsx_member_to_parts, position_to_string, span_to_position, }; use markdown::{unist::Position, Location}; +use swc_core::alloc::collections::FxHashSet; +use swc_core::common::SyntaxContext; use swc_core::common::{util::take::Take, Span, DUMMY_SP}; use swc_core::ecma::ast::{ ArrowExpr, AssignPatProp, BinaryOp, BindingIdent, BlockStmt, BlockStmtOrExpr, Callee, @@ -41,6 +43,7 @@ pub fn mdx_plugin_recma_jsx_rewrite( program: &mut Program, options: &Options, location: Option<&Location>, + explicit_jsxs: FxHashSet, ) { let mut state = State { scopes: vec![], @@ -50,6 +53,7 @@ pub fn mdx_plugin_recma_jsx_rewrite( development: options.development, create_provider_import: false, create_error_helper: false, + explicit_jsxs, }; state.enter(Some(Info::default())); program.module.visit_mut_with(&mut state); @@ -152,6 +156,8 @@ struct State<'a> { /// When things are referenced that might not be defined, we reference a /// helper function to throw when they are missing. create_error_helper: bool, + + explicit_jsxs: FxHashSet, } impl<'a> State<'a> { @@ -292,7 +298,7 @@ impl<'a> State<'a> { let declarator = VarDeclarator { span: DUMMY_SP, name: Pat::Ident(BindingIdent { - id: create_ident("_components"), + id: create_ident("_components").into(), type_ann: None, }), init: Some(Box::new(components_init)), @@ -316,7 +322,7 @@ impl<'a> State<'a> { let declarator = VarDeclarator { span: DUMMY_SP, name: Pat::Ident(BindingIdent { - id: create_ident(&alias.safe), + id: create_ident(&alias.safe).into(), type_ann: None, }), init: Some(Box::new(Expr::Member(create_member( @@ -350,7 +356,7 @@ impl<'a> State<'a> { // `wrapper: MDXLayout` if reference.name == "MDXLayout" { let binding = BindingIdent { - id: create_ident(&reference.name), + id: create_ident(&reference.name).into(), type_ann: None, }; let prop = KeyValuePatProp { @@ -392,6 +398,7 @@ impl<'a> State<'a> { decls: declarators, span: DUMMY_SP, declare: false, + ctxt: SyntaxContext::empty(), }; let var_decl = Decl::Var(Box::new(decl)); statements.push(Stmt::Decl(var_decl)); @@ -480,6 +487,7 @@ impl<'a> State<'a> { span: DUMMY_SP, })], span: DUMMY_SP, + ctxt: SyntaxContext::empty(), }; arr.body = Box::new(BlockStmtOrExpr::BlockStmt(block)); } @@ -580,13 +588,13 @@ impl<'a> State<'a> { } } - fn ref_ids(&mut self, ids: &[String], span: &Span) -> Option { + fn ref_ids(&mut self, ids: &[String], span: Span) -> Option { // If there is a top-level, non-global, scope which is a function: if let Some(info) = self.current_top_level_info() { // Rewrite only if we can rewrite. if is_props_receiving_fn(&info.name) || self.provider { debug_assert!(!ids.is_empty(), "expected non-empty ids"); - let explicit_jsx = span.ctxt.as_u32() == MAGIC_EXPLICIT_MARKER; + let explicit_jsx = self.explicit_jsxs.contains(&span); let mut path = ids.to_owned(); let position = span_to_position(span, self.location); @@ -702,7 +710,7 @@ impl<'a> VisitMut for State<'a> { } }; - if let Some(name) = self.ref_ids(&parts, &node.span) { + if let Some(name) = self.ref_ids(&parts, node.span) { if let Some(closing) = node.closing.as_mut() { closing.name = name.clone(); } @@ -862,8 +870,10 @@ impl<'a> VisitMut for State<'a> { fn create_import_provider(source: &str) -> ModuleItem { ModuleItem::ModuleDecl(ModuleDecl::Import(ImportDecl { specifiers: vec![ImportSpecifier::Named(ImportNamedSpecifier { - local: create_ident("_provideComponents"), - imported: Some(ModuleExportName::Ident(create_ident("useMDXComponents"))), + local: create_ident("_provideComponents").into(), + imported: Some(ModuleExportName::Ident( + create_ident("useMDXComponents").into(), + )), span: DUMMY_SP, is_type_only: false, })], @@ -886,7 +896,7 @@ fn create_error_helper(development: bool, path: Option) -> ModuleItem { let mut parameters = vec![ Param { pat: Pat::Ident(BindingIdent { - id: create_ident("id"), + id: create_ident("id").into(), type_ann: None, }), decorators: vec![], @@ -894,7 +904,7 @@ fn create_error_helper(development: bool, path: Option) -> ModuleItem { }, Param { pat: Pat::Ident(BindingIdent { - id: create_ident("component"), + id: create_ident("component").into(), type_ann: None, }), decorators: vec![], @@ -906,7 +916,7 @@ fn create_error_helper(development: bool, path: Option) -> ModuleItem { if development { parameters.push(Param { pat: Pat::Ident(BindingIdent { - id: create_ident("place"), + id: create_ident("place").into(), type_ann: None, }), decorators: vec![], @@ -956,7 +966,7 @@ fn create_error_helper(development: bool, path: Option) -> ModuleItem { } ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl { - ident: create_ident("_missingMdxReference"), + ident: create_ident("_missingMdxReference").into(), declare: false, function: Box::new(Function { params: parameters, @@ -971,16 +981,19 @@ fn create_error_helper(development: bool, path: Option) -> ModuleItem { }]), span: DUMMY_SP, type_args: None, + ctxt: SyntaxContext::empty(), })), span: DUMMY_SP, })], span: DUMMY_SP, + ctxt: SyntaxContext::empty(), }), is_generator: false, is_async: false, type_params: None, return_type: None, span: DUMMY_SP, + ctxt: SyntaxContext::empty(), }), }))) } @@ -1026,9 +1039,12 @@ mod tests { } else { None }; - let mut program = hast_util_to_swc(&hast, filepath, Some(&location))?; + + let mut explicit_jsxs = FxHashSet::default(); + + let mut program = hast_util_to_swc(&hast, filepath, Some(&location), &mut explicit_jsxs)?; mdx_plugin_recma_document(&mut program, &DocumentOptions::default(), Some(&location))?; - mdx_plugin_recma_jsx_rewrite(&mut program, options, Some(&location)); + mdx_plugin_recma_jsx_rewrite(&mut program, options, Some(&location), explicit_jsxs); Ok(serialize(&mut program.module, Some(&program.comments))) } @@ -1815,6 +1831,8 @@ function _missingMdxReference(id, component, place) { #[test] fn jsx_outside_components() { + let explicit_jsxs = FxHashSet::default(); + let mut program = Program { path: None, comments: vec![], @@ -1826,7 +1844,7 @@ function _missingMdxReference(id, component, place) { decls: vec![VarDeclarator { span: DUMMY_SP, name: Pat::Ident(BindingIdent { - id: create_ident("a"), + id: create_ident("a").into(), type_ann: None, }), init: Some(Box::new(Expr::JSXElement(Box::new(JSXElement { @@ -1844,11 +1862,12 @@ function _missingMdxReference(id, component, place) { definite: false, }], span: DUMMY_SP, + ctxt: SyntaxContext::empty(), declare: false, }))))], }, }; - mdx_plugin_recma_jsx_rewrite(&mut program, &Options::default(), None); + mdx_plugin_recma_jsx_rewrite(&mut program, &Options::default(), None, explicit_jsxs); assert_eq!( serialize(&mut program.module, None), "let a = ;\n", @@ -1858,6 +1877,8 @@ function _missingMdxReference(id, component, place) { #[test] fn invalid_patterns() { + let explicit_jsxs = FxHashSet::default(); + let mut program = Program { path: None, comments: vec![], @@ -1874,10 +1895,11 @@ function _missingMdxReference(id, component, place) { }], span: DUMMY_SP, declare: false, + ctxt: SyntaxContext::empty(), }))))], }, }; - mdx_plugin_recma_jsx_rewrite(&mut program, &Options::default(), None); + mdx_plugin_recma_jsx_rewrite(&mut program, &Options::default(), None, explicit_jsxs); assert_eq!( serialize(&mut program.module, None), "let ;\n", @@ -1887,6 +1909,8 @@ function _missingMdxReference(id, component, place) { #[test] fn expr_patterns() { + let explicit_jsxs = FxHashSet::default(); + let mut program = Program { path: None, comments: vec![], @@ -1897,16 +1921,17 @@ function _missingMdxReference(id, component, place) { kind: VarDeclKind::Let, decls: vec![VarDeclarator { span: DUMMY_SP, - name: Pat::Expr(Box::new(Expr::Ident(create_ident("a")))), + name: Pat::Expr(Box::new(Expr::Ident(create_ident("a").into()))), init: None, definite: false, }], span: DUMMY_SP, declare: false, + ctxt: SyntaxContext::empty(), }))))], }, }; - mdx_plugin_recma_jsx_rewrite(&mut program, &Options::default(), None); + mdx_plugin_recma_jsx_rewrite(&mut program, &Options::default(), None, explicit_jsxs); assert_eq!( serialize(&mut program.module, None), "let a;\n", diff --git a/src/swc.rs b/src/swc.rs index 4e969ce..962dc73 100644 --- a/src/swc.rs +++ b/src/swc.rs @@ -7,7 +7,7 @@ use markdown::{mdast::Stop, Location, MdxExpressionKind, MdxSignal}; use std::rc::Rc; use swc_core::common::{ comments::{Comment, Comments, SingleThreadedComments, SingleThreadedCommentsMap}, - source_map::Pos, + source_map::SmallPos, sync::Lrc, BytePos, FileName, FilePathMapping, SourceFile, SourceMap, Span, Spanned, }; @@ -354,9 +354,9 @@ fn create_config(source: String) -> (SourceFile, Syntax, EsVersion) { ( // File. SourceFile::new( - FileName::Anon, + FileName::Anon.into(), false, - FileName::Anon, + FileName::Anon.into(), source, BytePos::from_usize(1), ), diff --git a/src/swc_util_build_jsx.rs b/src/swc_util_build_jsx.rs index 000d1e6..db61954 100644 --- a/src/swc_util_build_jsx.rs +++ b/src/swc_util_build_jsx.rs @@ -11,6 +11,7 @@ use crate::swc_utils::{ }; use core::str; use markdown::{message::Message, Location}; +use swc_core::common::SyntaxContext; use swc_core::common::{ comments::{Comment, CommentKind}, util::take::Take, @@ -71,8 +72,8 @@ pub fn swc_util_build_jsx( if state.import_fragment { specifiers.push(ImportSpecifier::Named(ImportNamedSpecifier { - local: create_ident("_Fragment"), - imported: Some(ModuleExportName::Ident(create_ident("Fragment"))), + local: create_ident("_Fragment").into(), + imported: Some(ModuleExportName::Ident(create_ident("Fragment").into())), span: swc_core::common::DUMMY_SP, is_type_only: false, })); @@ -80,8 +81,8 @@ pub fn swc_util_build_jsx( if state.import_jsx { specifiers.push(ImportSpecifier::Named(ImportNamedSpecifier { - local: create_ident("_jsx"), - imported: Some(ModuleExportName::Ident(create_ident("jsx"))), + local: create_ident("_jsx").into(), + imported: Some(ModuleExportName::Ident(create_ident("jsx").into())), span: swc_core::common::DUMMY_SP, is_type_only: false, })); @@ -89,8 +90,8 @@ pub fn swc_util_build_jsx( if state.import_jsxs { specifiers.push(ImportSpecifier::Named(ImportNamedSpecifier { - local: create_ident("_jsxs"), - imported: Some(ModuleExportName::Ident(create_ident("jsxs"))), + local: create_ident("_jsxs").into(), + imported: Some(ModuleExportName::Ident(create_ident("jsxs").into())), span: swc_core::common::DUMMY_SP, is_type_only: false, })); @@ -98,8 +99,8 @@ pub fn swc_util_build_jsx( if state.import_jsx_dev { specifiers.push(ImportSpecifier::Named(ImportNamedSpecifier { - local: create_ident("_jsxDEV"), - imported: Some(ModuleExportName::Ident(create_ident("jsxDEV"))), + local: create_ident("_jsxDEV").into(), + imported: Some(ModuleExportName::Ident(create_ident("jsxDEV").into())), span: swc_core::common::DUMMY_SP, is_type_only: false, })); @@ -375,7 +376,7 @@ impl<'a> State<'a> { /// Turn the parsed parts from fragments or elements into a call. fn jsx_expressions_to_call( &mut self, - span: &swc_core::common::Span, + span: swc_core::common::Span, name: Expr, attributes: Option>, mut children: Vec, @@ -546,7 +547,8 @@ impl<'a> State<'a> { callee: Callee::Expr(Box::new(callee)), args: parameters, type_args: None, - span: *span, + span, + ctxt: SyntaxContext::empty(), }; Ok(Expr::Call(call_expression)) @@ -569,7 +571,7 @@ impl<'a> State<'a> { } } - self.jsx_expressions_to_call(&element.span, name, Some(element.opening.attrs), children) + self.jsx_expressions_to_call(element.span, name, Some(element.opening.attrs), children) } /// Turn a JSX fragment into an expression. @@ -584,7 +586,7 @@ impl<'a> State<'a> { self.fragment_expression.clone() }; let children = self.jsx_children_to_expressions(fragment.children)?; - self.jsx_expressions_to_call(&fragment.span, name, None, children) + self.jsx_expressions_to_call(fragment.span, name, None, children) } } @@ -801,7 +803,7 @@ mod tests { use pretty_assertions::assert_eq; use swc_core::common::Spanned; use swc_core::common::{ - comments::SingleThreadedComments, source_map::Pos, BytePos, FileName, SourceFile, + comments::SingleThreadedComments, source_map::SmallPos, BytePos, FileName, SourceFile, }; use swc_core::ecma::ast::{ EsVersion, ExprStmt, JSXClosingElement, JSXElementName, JSXOpeningElement, JSXSpreadChild, @@ -815,9 +817,9 @@ mod tests { let comments = SingleThreadedComments::default(); let result = parse_file_as_module( &SourceFile::new( - FileName::Anon, + FileName::Anon.into(), false, - FileName::Anon, + FileName::Anon.into(), value.into(), BytePos::from_usize(1), ), @@ -1357,14 +1359,14 @@ _jsx(\"a\", { expr: Box::new(Expr::JSXElement(Box::new(JSXElement { span: swc_core::common::DUMMY_SP, opening: JSXOpeningElement { - name: JSXElementName::Ident(create_ident("a")), + name: JSXElementName::Ident(create_ident("a").into()), attrs: vec![], self_closing: false, type_args: None, span: swc_core::common::DUMMY_SP, }, closing: Some(JSXClosingElement { - name: JSXElementName::Ident(create_ident("a")), + name: JSXElementName::Ident(create_ident("a").into()), span: swc_core::common::DUMMY_SP, }), children: vec![JSXElementChild::JSXSpreadChild(JSXSpreadChild { @@ -1569,7 +1571,7 @@ _jsxDEV(_Fragment, { expr: Box::new(Expr::JSXElement(Box::new(JSXElement { span: swc_core::common::DUMMY_SP, opening: JSXOpeningElement { - name: JSXElementName::Ident(create_ident("a")), + name: JSXElementName::Ident(create_ident("a").into()), attrs: vec![], self_closing: true, type_args: None, diff --git a/src/swc_utils.rs b/src/swc_utils.rs index b9a6de8..1124b57 100644 --- a/src/swc_utils.rs +++ b/src/swc_utils.rs @@ -8,13 +8,16 @@ use markdown::{ Location, }; -use swc_core::common::{BytePos, Span, SyntaxContext, DUMMY_SP}; use swc_core::ecma::ast::{ BinExpr, BinaryOp, Bool, CallExpr, Callee, ComputedPropName, Expr, ExprOrSpread, Ident, JSXAttrName, JSXElementName, JSXMemberExpr, JSXNamespacedName, JSXObject, Lit, MemberExpr, MemberProp, Null, Number, ObjectLit, PropName, PropOrSpread, Str, }; use swc_core::ecma::visit::{noop_visit_mut_type, VisitMut}; +use swc_core::{ + common::{BytePos, Span, SyntaxContext, DUMMY_SP}, + ecma::ast::IdentName, +}; /// Turn a unist position, into an SWC span, of two byte positions. /// @@ -24,7 +27,6 @@ pub fn position_to_span(position: Option<&Position>) -> Span { position.map_or(DUMMY_SP, |d| Span { lo: point_to_bytepos(&d.start), hi: point_to_bytepos(&d.end), - ctxt: SyntaxContext::empty(), }) } @@ -34,7 +36,7 @@ pub fn position_to_span(position: Option<&Position>) -> Span { /// /// > 👉 **Note**: SWC byte positions are offset by one: they are `0` when they /// > are missing or incremented by `1` when valid. -pub fn span_to_position(span: &Span, location: Option<&Location>) -> Option { +pub fn span_to_position(span: Span, location: Option<&Location>) -> Option { let lo = span.lo.0 as usize; let hi = span.hi.0 as usize; @@ -177,7 +179,6 @@ pub fn create_span(lo: u32, hi: u32) -> Span { Span { lo: BytePos(lo), hi: BytePos(hi), - ctxt: SyntaxContext::default(), } } @@ -186,10 +187,9 @@ pub fn create_span(lo: u32, hi: u32) -> Span { /// ```js /// a /// ``` -pub fn create_ident(sym: &str) -> Ident { - Ident { +pub fn create_ident(sym: &str) -> IdentName { + IdentName { sym: sym.into(), - optional: false, span: DUMMY_SP, } } @@ -200,7 +200,7 @@ pub fn create_ident(sym: &str) -> Ident { /// a /// ``` pub fn create_ident_expression(sym: &str) -> Expr { - Expr::Ident(create_ident(sym)) + Expr::Ident(create_ident(sym).into()) } /// Generate a null. @@ -285,6 +285,7 @@ pub fn create_call(callee: Callee, args: Vec) -> CallExpr { args, span: DUMMY_SP, type_args: None, + ctxt: SyntaxContext::empty(), } } @@ -379,16 +380,17 @@ pub fn create_member_prop_from_str(name: &str) -> MemberProp { pub fn create_jsx_name_from_str(name: &str) -> JSXElementName { match parse_jsx_name(name) { // `a` - JsxName::Normal(name) => JSXElementName::Ident(create_ident(name)), + JsxName::Normal(name) => JSXElementName::Ident(create_ident(name).into()), // `a:b` JsxName::Namespace(ns, name) => JSXElementName::JSXNamespacedName(JSXNamespacedName { + span: DUMMY_SP, ns: create_ident(ns), name: create_ident(name), }), // `a.b.c` JsxName::Member(parts) => { let mut member = create_jsx_member( - JSXObject::Ident(create_ident(parts[0])), + JSXObject::Ident(create_ident(parts[0]).into()), create_ident(parts[1]), ); let mut index = 2; @@ -405,8 +407,12 @@ pub fn create_jsx_name_from_str(name: &str) -> JSXElementName { } /// Generate a member expression from an object and prop. -pub fn create_jsx_member(obj: JSXObject, prop: Ident) -> JSXMemberExpr { - JSXMemberExpr { obj, prop } +pub fn create_jsx_member(obj: JSXObject, prop: IdentName) -> JSXMemberExpr { + JSXMemberExpr { + span: DUMMY_SP, + obj, + prop, + } } /// Turn an JSX element name into an expression. @@ -431,6 +437,7 @@ pub fn create_jsx_attr_name_from_str(name: &str) -> JSXAttrName { } // `` JsxName::Namespace(ns, name) => JSXAttrName::JSXNamespacedName(JSXNamespacedName { + span: DUMMY_SP, ns: create_ident(ns), name: create_ident(name), }), @@ -448,11 +455,10 @@ pub fn jsx_member_expression_to_expression(node: JSXMemberExpr) -> Expr { } /// Turn an ident into a member prop. -pub fn ident_to_member_prop(node: &Ident) -> MemberProp { +pub fn ident_to_member_prop(node: &IdentName) -> MemberProp { if is_identifier_name(node.as_ref()) { - MemberProp::Ident(Ident { + MemberProp::Ident(IdentName { sym: node.sym.clone(), - optional: false, span: node.span, }) } else { @@ -652,8 +658,9 @@ mod tests { fn jsx_member_to_parts_test() { assert_eq!( jsx_member_to_parts(&JSXMemberExpr { + span: DUMMY_SP, prop: create_ident("a"), - obj: JSXObject::Ident(create_ident("b")) + obj: JSXObject::Ident(create_ident("b").into()) }), vec!["b", "a"], "should support a member with 2 items" @@ -661,12 +668,15 @@ mod tests { assert_eq!( jsx_member_to_parts(&JSXMemberExpr { + span: DUMMY_SP, prop: create_ident("a"), obj: JSXObject::JSXMemberExpr(Box::new(JSXMemberExpr { + span: DUMMY_SP, prop: create_ident("b"), obj: JSXObject::JSXMemberExpr(Box::new(JSXMemberExpr { + span: DUMMY_SP, prop: create_ident("c"), - obj: JSXObject::Ident(create_ident("d")) + obj: JSXObject::Ident(create_ident("d").into()) })) })) }), diff --git a/tests/test.rs b/tests/test.rs index 1adcac0..3722e71 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -339,7 +339,7 @@ fn err_expression_broken_multiline_comment_b() { .err() .unwrap() .to_string(), - "1:2: Could not parse expression with swc: Unexpected eof (mdxjs-rs:swc)", + "1:6: Could not parse expression with swc: Unexpected eof (mdxjs-rs:swc)", "should crash on an unclosed block comment in an empty expression", ); } @@ -368,7 +368,7 @@ fn err_expression_broken_line_comment_b() { .err() .unwrap() .to_string(), - "1:2: Could not parse expression with swc: Unexpected eof (mdxjs-rs:swc)", + "1:6: Could not parse expression with swc: Unexpected eof (mdxjs-rs:swc)", "should crash on an unclosed line comment in an empty expression", ); } @@ -440,7 +440,7 @@ fn err_expression_value_empty() { .err() .unwrap() .to_string(), - "1:7: Could not parse expression with swc: Unexpected eof (mdxjs-rs:swc)", + "1:12: Could not parse expression with swc: Unexpected eof (mdxjs-rs:swc)", "should crash on an empty value expression", ); } @@ -464,7 +464,7 @@ fn err_expression_value_comment() { .err() .unwrap() .to_string(), - "1:7: Could not parse expression with swc: Unexpected eof (mdxjs-rs:swc)", + "1:18: Could not parse expression with swc: Unexpected eof (mdxjs-rs:swc)", "should crash on a value expression with just a comment", ); }