mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
fix(ast)!: always return Array<ImportDeclarationSpecifier> for ImportDeclaration.specifiers (#8560)
refs https://github.com/oxc-project/oxc/issues/2854#issuecomment-2595115817
This commit is contained in:
parent
869bc73e67
commit
19d36771af
6 changed files with 34 additions and 3 deletions
|
|
@ -2196,6 +2196,7 @@ pub struct ImportExpression<'a> {
|
|||
pub struct ImportDeclaration<'a> {
|
||||
pub span: Span,
|
||||
/// `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'`
|
||||
#[estree(with = "OptionVecDefault", type = "Array<ImportDeclarationSpecifier>")]
|
||||
pub specifiers: Option<Vec<'a, ImportDeclarationSpecifier<'a>>>,
|
||||
pub source: StringLiteral<'a>,
|
||||
pub phase: Option<ImportPhase>,
|
||||
|
|
|
|||
|
|
@ -1696,7 +1696,7 @@ impl Serialize for ImportDeclaration<'_> {
|
|||
let mut map = serializer.serialize_map(None)?;
|
||||
map.serialize_entry("type", "ImportDeclaration")?;
|
||||
self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?;
|
||||
map.serialize_entry("specifiers", &self.specifiers)?;
|
||||
map.serialize_entry("specifiers", &crate::serialize::OptionVecDefault(&self.specifiers))?;
|
||||
map.serialize_entry("source", &self.source)?;
|
||||
map.serialize_entry("phase", &self.phase)?;
|
||||
map.serialize_entry("withClause", &self.with_clause)?;
|
||||
|
|
|
|||
|
|
@ -241,6 +241,18 @@ impl<E: Serialize, R: Serialize> Serialize for ElementsAndRest<'_, E, R> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct OptionVecDefault<'a, 'b, T: Serialize>(pub &'a Option<oxc_allocator::Vec<'b, T>>);
|
||||
|
||||
impl<T: Serialize> Serialize for OptionVecDefault<'_, '_, T> {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
if let Some(vec) = &self.0 {
|
||||
vec.serialize(serializer)
|
||||
} else {
|
||||
[false; 0].serialize(serializer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Serialize `TSModuleBlock` to be ESTree compatible, with `body` and `directives` fields combined,
|
||||
/// and directives output as `StringLiteral` expression statements
|
||||
impl Serialize for TSModuleBlock<'_> {
|
||||
|
|
|
|||
2
npm/oxc-types/types.d.ts
vendored
2
npm/oxc-types/types.d.ts
vendored
|
|
@ -911,7 +911,7 @@ export interface ImportExpression extends Span {
|
|||
|
||||
export interface ImportDeclaration extends Span {
|
||||
type: 'ImportDeclaration';
|
||||
specifiers: Array<ImportDeclarationSpecifier> | null;
|
||||
specifiers: Array<ImportDeclarationSpecifier>;
|
||||
source: StringLiteral;
|
||||
phase: ImportPhase | null;
|
||||
withClause: WithClause | null;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use crate::{
|
|||
serialize::{enum_variant_name, get_always_flatten_structs, get_type_tag},
|
||||
EnumDef, FieldDef, GetGenerics, GetIdent, Schema, StructDef, TypeDef,
|
||||
},
|
||||
util::ToIdent,
|
||||
};
|
||||
|
||||
use super::{define_derive, Derive};
|
||||
|
|
@ -141,6 +142,14 @@ fn serialize_struct(def: &StructDef, schema: &Schema) -> TokenStream {
|
|||
}
|
||||
)?;
|
||||
});
|
||||
} else if let Some(with) = &field.markers.derive_attributes.estree.with {
|
||||
let with_ident = with.to_ident();
|
||||
fields.push(quote! {
|
||||
map.serialize_entry(
|
||||
#name,
|
||||
&crate::serialize::#with_ident(&self.#ident)
|
||||
)?;
|
||||
});
|
||||
} else {
|
||||
fields.push(quote! {
|
||||
map.serialize_entry(#name, &self.#ident)?;
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ pub struct ESTreeFieldAttribute {
|
|||
pub rename: Option<String>,
|
||||
pub typescript_type: Option<String>,
|
||||
pub append_to: Option<String>,
|
||||
pub with: Option<String>,
|
||||
}
|
||||
|
||||
impl Parse for ESTreeFieldAttribute {
|
||||
|
|
@ -236,6 +237,7 @@ impl Parse for ESTreeFieldAttribute {
|
|||
let mut rename = None;
|
||||
let mut typescript_type = None;
|
||||
let mut append_to = None;
|
||||
let mut with = None;
|
||||
|
||||
loop {
|
||||
let is_type = input.peek(Token![type]);
|
||||
|
|
@ -281,6 +283,13 @@ impl Parse for ESTreeFieldAttribute {
|
|||
"Duplicate estree(append_to)"
|
||||
);
|
||||
}
|
||||
"with" => {
|
||||
input.parse::<Token![=]>()?;
|
||||
assert!(
|
||||
with.replace(input.parse::<LitStr>()?.value()).is_none(),
|
||||
"Duplicate estree(with)"
|
||||
);
|
||||
}
|
||||
arg => panic!("Unsupported #[estree(...)] argument: {arg}"),
|
||||
}
|
||||
let comma = input.peek(Token![,]);
|
||||
|
|
@ -290,7 +299,7 @@ impl Parse for ESTreeFieldAttribute {
|
|||
break;
|
||||
}
|
||||
}
|
||||
Ok(Self { flatten, skip, rename, typescript_type, append_to })
|
||||
Ok(Self { flatten, skip, rename, typescript_type, append_to, with })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue