From 819fc88a19a927091e8ce093d9eab518da039138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Sat, 11 Dec 2021 05:58:11 +0100 Subject: [PATCH] fix(es/dep_graph): Fix parsing of import assertions (#3005) --- crates/swc_ecma_dep_graph/src/lib.rs | 90 +++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 9 deletions(-) diff --git a/crates/swc_ecma_dep_graph/src/lib.rs b/crates/swc_ecma_dep_graph/src/lib.rs index acab5aabc575..1203ad1c8b3c 100644 --- a/crates/swc_ecma_dep_graph/src/lib.rs +++ b/crates/swc_ecma_dep_graph/src/lib.rs @@ -171,6 +171,38 @@ impl<'a> Visit for DependencyCollector<'a> { if let ast::Lit::Str(str_) = lit { let specifier = str_.value.clone(); let leading_comments = self.get_leading_comments(node.span); + let mut import_assertions = HashMap::default(); + + if let Some(arg) = node.args.get(1) { + if let Object(object_lit) = &*arg.expr { + for prop in object_lit.props.iter() { + if let ast::PropOrSpread::Prop(prop) = prop { + if let ast::Prop::KeyValue(key_value) = &**prop { + let maybe_key = match &key_value.key { + ast::PropName::Str(key) => Some(key.value.to_string()), + ast::PropName::Ident(ident) => { + Some(ident.sym.to_string()) + } + _ => None, + }; + + if let Some(key) = maybe_key { + if key == "assert" { + import_assertions = if let Object(assertions_lit) = + &*key_value.value + { + parse_import_assertions(Some(&assertions_lit)) + } else { + HashMap::new() + }; + } + } + } + } + } + } + } + self.items.push(DependencyDescriptor { kind, is_dynamic, @@ -178,7 +210,7 @@ impl<'a> Visit for DependencyCollector<'a> { span: node.span, specifier, specifier_span: str_.span, - import_assertions: HashMap::default(), + import_assertions, }); } } @@ -192,13 +224,23 @@ impl<'a> Visit for DependencyCollector<'a> { fn parse_import_assertions(asserts: Option<&ast::ObjectLit>) -> HashMap { let mut import_assertions = HashMap::new(); if let Some(asserts) = asserts { - for prop in &asserts.props { - let prop = prop.clone().expect_prop(); - let key_value = prop.expect_key_value(); - let key = key_value.key.expect_str().value.to_string(); - let value_lit = key_value.value.expect_lit(); - if let ast::Lit::Str(str_) = value_lit { - import_assertions.insert(key, str_.value.to_string()); + for prop in asserts.props.iter() { + if let ast::PropOrSpread::Prop(prop) = prop { + if let ast::Prop::KeyValue(key_value) = &**prop { + let maybe_key = match &key_value.key { + ast::PropName::Str(key) => Some(key.value.to_string()), + ast::PropName::Ident(ident) => Some(ident.sym.to_string()), + _ => None, + }; + + if let Some(key) = maybe_key { + if let ast::Expr::Lit(value_lit) = &*key_value.value { + if let ast::Lit::Str(str_) = value_lit { + import_assertions.insert(key, str_.value.to_string()); + } + } + } + } } } } @@ -392,6 +434,9 @@ try { let source = r#"import * as bar from "./test.ts" assert { "type": "typescript" }; export * from "./test.ts" assert { "type": "typescript" }; export { bar } from "./test.json" assert { "type": "json" }; +import foo from "./foo.json" assert { type: "json" }; +const fizz = await import("./fizz.json", { "assert": { type: "json" } }); +const buzz = await import("./buzz.json", { assert: { "type": "json" } }); "#; let (module, comments) = helper("test.ts", &source).unwrap(); let mut expected_assertions1 = HashMap::new(); @@ -399,7 +444,7 @@ export { bar } from "./test.json" assert { "type": "json" }; let mut expected_assertions2 = HashMap::new(); expected_assertions2.insert("type".to_string(), "json".to_string()); let dependencies = analyze_dependencies(&module, &comments); - assert_eq!(dependencies.len(), 3); + assert_eq!(dependencies.len(), 6); assert_eq!( dependencies, vec![ @@ -428,6 +473,33 @@ export { bar } from "./test.json" assert { "type": "json" }; span: Span::new(BytePos(125), BytePos(185), Default::default()), specifier: JsWord::from("./test.json"), specifier_span: Span::new(BytePos(145), BytePos(158), Default::default()), + import_assertions: expected_assertions2.clone(), + }, + DependencyDescriptor { + kind: DependencyKind::Import, + is_dynamic: false, + leading_comments: Vec::new(), + span: Span::new(BytePos(186), BytePos(239), Default::default()), + specifier: JsWord::from("./foo.json"), + specifier_span: Span::new(BytePos(202), BytePos(214), Default::default()), + import_assertions: expected_assertions2.clone(), + }, + DependencyDescriptor { + kind: DependencyKind::Import, + is_dynamic: true, + leading_comments: Vec::new(), + span: Span::new(BytePos(259), BytePos(312), Default::default()), + specifier: JsWord::from("./fizz.json"), + specifier_span: Span::new(BytePos(266), BytePos(279), Default::default()), + import_assertions: expected_assertions2.clone(), + }, + DependencyDescriptor { + kind: DependencyKind::Import, + is_dynamic: true, + leading_comments: Vec::new(), + span: Span::new(BytePos(333), BytePos(386), Default::default()), + specifier: JsWord::from("./buzz.json"), + specifier_span: Span::new(BytePos(340), BytePos(353), Default::default()), import_assertions: expected_assertions2, }, ]