diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index 940f8de2902a6..657221d9b6d91 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -1289,9 +1289,12 @@ pub struct TSImportType<'a> { #[ast(visit)] #[derive(Debug)] #[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ESTree)] +#[estree(ts_alias = "ObjectExpression")] pub struct TSImportAttributes<'a> { pub span: Span, + #[estree(skip)] pub attributes_keyword: IdentifierName<'a>, // `with` or `assert` + #[estree(rename = "properties", via = TSImportAttributesProperties)] pub elements: Vec<'a, TSImportAttribute<'a>>, } @@ -1300,8 +1303,15 @@ pub struct TSImportAttributes<'a> { #[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ESTree)] // Pluralize as `TSImportAttributeList` to avoid naming clash with `TSImportAttributes`. #[plural(TSImportAttributeList)] +#[estree( + no_ts_def, + rename = "Property", + add_fields(method = False, shorthand = True, computed = False, kind = Init), + field_order(span, method, shorthand, computed, name, value, kind), +)] pub struct TSImportAttribute<'a> { pub span: Span, + #[estree(rename = "key")] pub name: TSImportAttributeName<'a>, pub value: Expression<'a>, } @@ -1309,6 +1319,7 @@ pub struct TSImportAttribute<'a> { #[ast(visit)] #[derive(Debug)] #[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ESTree)] +#[estree(no_ts_def)] pub enum TSImportAttributeName<'a> { Identifier(IdentifierName<'a>) = 0, StringLiteral(StringLiteral<'a>) = 1, diff --git a/crates/oxc_ast/src/generated/derive_estree.rs b/crates/oxc_ast/src/generated/derive_estree.rs index 3393dc7f31dec..03dc369246bcb 100644 --- a/crates/oxc_ast/src/generated/derive_estree.rs +++ b/crates/oxc_ast/src/generated/derive_estree.rs @@ -3106,8 +3106,7 @@ impl ESTree for TSImportAttributes<'_> { state.serialize_field("type", &JsonSafeString("TSImportAttributes")); state.serialize_field("start", &self.span.start); state.serialize_field("end", &self.span.end); - state.serialize_field("attributesKeyword", &self.attributes_keyword); - state.serialize_field("elements", &self.elements); + state.serialize_field("properties", &crate::serialize::TSImportAttributesProperties(self)); state.end(); } } @@ -3115,11 +3114,15 @@ impl ESTree for TSImportAttributes<'_> { impl ESTree for TSImportAttribute<'_> { fn serialize(&self, serializer: S) { let mut state = serializer.serialize_struct(); - state.serialize_field("type", &JsonSafeString("TSImportAttribute")); + state.serialize_field("type", &JsonSafeString("Property")); state.serialize_field("start", &self.span.start); state.serialize_field("end", &self.span.end); - state.serialize_field("name", &self.name); + state.serialize_field("method", &crate::serialize::False(self)); + state.serialize_field("shorthand", &crate::serialize::True(self)); + state.serialize_field("computed", &crate::serialize::False(self)); + state.serialize_field("key", &self.name); state.serialize_field("value", &self.value); + state.serialize_field("kind", &crate::serialize::Init(self)); state.end(); } } diff --git a/crates/oxc_ast/src/serialize.rs b/crates/oxc_ast/src/serialize.rs index 38aab4d1b42fe..dcfa56427dc7a 100644 --- a/crates/oxc_ast/src/serialize.rs +++ b/crates/oxc_ast/src/serialize.rs @@ -505,6 +505,75 @@ impl ESTree for ExportAllDeclarationWithClause<'_, '_> { } } +#[ast_meta] +#[estree(raw_deser = " + const start = DESER[u32](POS_OFFSET.span.start); + const end = DESER[u32](POS_OFFSET.span.end); + const attributesKeyword = DESER[IdentifierName](POS_OFFSET.attributes_keyword); + const properties = DESER[Vec](POS_OFFSET.elements); + const result = [ + { + type: 'Property', + start, + end, + method: false, + shorthand: false, + computed: false, + key: attributesKeyword, + value: { + type: 'ObjectExpression', + start, + end, + properties, + }, + kind: 'init', + }, + ]; + result + ")] +pub struct TSImportAttributesProperties<'a, 'b>(pub &'b TSImportAttributes<'a>); + +impl ESTree for TSImportAttributesProperties<'_, '_> { + fn serialize(&self, serializer: S) { + let mut state = serializer.serialize_sequence(); + state.serialize_element(&TSImportAttributesPropertiesWithProperty(self.0)); + state.end(); + } +} + +pub struct TSImportAttributesPropertiesWithProperty<'a, 'b>(pub &'b TSImportAttributes<'a>); + +impl ESTree for TSImportAttributesPropertiesWithProperty<'_, '_> { + fn serialize(&self, serializer: S) { + let mut state = serializer.serialize_struct(); + state.serialize_field("type", &JsonSafeString("Property")); + // TODO: span + state.serialize_field("start", &self.0.span.end); + state.serialize_field("end", &self.0.span.end); + state.serialize_field("method", &false); + state.serialize_field("shorthand", &false); + state.serialize_field("computed", &false); + state.serialize_field("key", &self.0.attributes_keyword); + state.serialize_field("value", &TSImportAttributesPropertiesWithPropertyValue(self.0)); + state.serialize_field("kind", &"init"); + state.end(); + } +} + +struct TSImportAttributesPropertiesWithPropertyValue<'a, 'b>(&'b TSImportAttributes<'a>); + +impl ESTree for TSImportAttributesPropertiesWithPropertyValue<'_, '_> { + fn serialize(&self, serializer: S) { + let mut state = serializer.serialize_struct(); + state.serialize_field("type", &JsonSafeString("ObjectExpression")); + // TODO: span + state.serialize_field("start", &self.0.span.start); + state.serialize_field("end", &self.0.span.end); + state.serialize_field("properties", &self.0.elements); + state.end(); + } +} + // -------------------- // JSX // -------------------- diff --git a/napi/parser/deserialize-js.js b/napi/parser/deserialize-js.js index 069db022e954b..467ef43b0fbbf 100644 --- a/napi/parser/deserialize-js.js +++ b/napi/parser/deserialize-js.js @@ -1780,22 +1780,47 @@ function deserializeTSImportType(pos) { } function deserializeTSImportAttributes(pos) { + const start = deserializeU32(pos); + const end = deserializeU32(pos + 4); + const attributesKeyword = deserializeIdentifierName(pos + 8); + const properties = deserializeVecTSImportAttribute(pos + 32); + const result = [ + { + type: 'Property', + start, + end, + method: false, + shorthand: false, + computed: false, + key: attributesKeyword, + value: { + type: 'ObjectExpression', + start, + end, + properties, + }, + kind: 'init', + }, + ]; return { type: 'TSImportAttributes', start: deserializeU32(pos), end: deserializeU32(pos + 4), - attributesKeyword: deserializeIdentifierName(pos + 8), - elements: deserializeVecTSImportAttribute(pos + 32), + properties: result, }; } function deserializeTSImportAttribute(pos) { return { - type: 'TSImportAttribute', + type: 'Property', start: deserializeU32(pos), end: deserializeU32(pos + 4), - name: deserializeTSImportAttributeName(pos + 8), + method: false, + shorthand: true, + computed: false, + key: deserializeTSImportAttributeName(pos + 8), value: deserializeExpression(pos + 56), + kind: 'init', }; } diff --git a/napi/parser/deserialize-ts.js b/napi/parser/deserialize-ts.js index 18fbff6891e57..e323c51e5bd6d 100644 --- a/napi/parser/deserialize-ts.js +++ b/napi/parser/deserialize-ts.js @@ -1833,22 +1833,47 @@ function deserializeTSImportType(pos) { } function deserializeTSImportAttributes(pos) { + const start = deserializeU32(pos); + const end = deserializeU32(pos + 4); + const attributesKeyword = deserializeIdentifierName(pos + 8); + const properties = deserializeVecTSImportAttribute(pos + 32); + const result = [ + { + type: 'Property', + start, + end, + method: false, + shorthand: false, + computed: false, + key: attributesKeyword, + value: { + type: 'ObjectExpression', + start, + end, + properties, + }, + kind: 'init', + }, + ]; return { type: 'TSImportAttributes', start: deserializeU32(pos), end: deserializeU32(pos + 4), - attributesKeyword: deserializeIdentifierName(pos + 8), - elements: deserializeVecTSImportAttribute(pos + 32), + properties: result, }; } function deserializeTSImportAttribute(pos) { return { - type: 'TSImportAttribute', + type: 'Property', start: deserializeU32(pos), end: deserializeU32(pos + 4), - name: deserializeTSImportAttributeName(pos + 8), + method: false, + shorthand: true, + computed: false, + key: deserializeTSImportAttributeName(pos + 8), value: deserializeExpression(pos + 56), + kind: 'init', }; } diff --git a/npm/oxc-types/types.d.ts b/npm/oxc-types/types.d.ts index ca2db41313217..cade0c68637f0 100644 --- a/npm/oxc-types/types.d.ts +++ b/npm/oxc-types/types.d.ts @@ -1282,26 +1282,12 @@ export type TSTypeQueryExprName = TSImportType | TSTypeName; export interface TSImportType extends Span { type: 'TSImportType'; argument: TSType; - options: TSImportAttributes | null; + options: ObjectExpression | null; qualifier: TSTypeName | null; typeArguments: TSTypeParameterInstantiation | null; isTypeOf: boolean; } -export interface TSImportAttributes extends Span { - type: 'TSImportAttributes'; - attributesKeyword: IdentifierName; - elements: Array; -} - -export interface TSImportAttribute extends Span { - type: 'TSImportAttribute'; - name: TSImportAttributeName; - value: Expression; -} - -export type TSImportAttributeName = IdentifierName | StringLiteral; - export interface TSFunctionType extends Span { type: 'TSFunctionType'; typeParameters: TSTypeParameterDeclaration | null; @@ -1789,8 +1775,6 @@ export type Node = | TSInferType | TSTypeQuery | TSImportType - | TSImportAttributes - | TSImportAttribute | TSFunctionType | TSConstructorType | TSMappedType