diff --git a/crates/oxc_ast/src/ast/literal.rs b/crates/oxc_ast/src/ast/literal.rs index 2f1f014749e8f..97b95bc35b006 100644 --- a/crates/oxc_ast/src/ast/literal.rs +++ b/crates/oxc_ast/src/ast/literal.rs @@ -65,6 +65,7 @@ pub struct NumericLiteral<'a> { #[ast(visit)] #[derive(Debug, Clone)] #[generate_derive(CloneIn, GetSpan, GetSpanMut, ContentEq, ContentHash, ESTree)] +#[estree(type = "Literal", via = crate::serialize::ESTreeLiteral, add_ts = "raw?: undefined")] pub struct StringLiteral<'a> { /// Node location in source code pub span: Span, diff --git a/crates/oxc_ast/src/generated/derive_estree.rs b/crates/oxc_ast/src/generated/derive_estree.rs index b0ec20342ddcb..e4964b858642e 100644 --- a/crates/oxc_ast/src/generated/derive_estree.rs +++ b/crates/oxc_ast/src/generated/derive_estree.rs @@ -33,11 +33,7 @@ impl<'a> Serialize for NumericLiteral<'a> { impl<'a> Serialize for StringLiteral<'a> { fn serialize(&self, serializer: S) -> Result { - let mut map = serializer.serialize_map(None)?; - map.serialize_entry("type", "StringLiteral")?; - self.span.serialize(serde::__private::ser::FlatMapSerializer(&mut map))?; - map.serialize_entry("value", &self.value)?; - map.end() + crate::serialize::ESTreeLiteral::from(self).serialize(serializer) } } diff --git a/crates/oxc_ast/src/serialize.rs b/crates/oxc_ast/src/serialize.rs index 66cab18770721..f5461e6f6241f 100644 --- a/crates/oxc_ast/src/serialize.rs +++ b/crates/oxc_ast/src/serialize.rs @@ -22,7 +22,7 @@ pub struct ESTreeLiteral<'a, T> { #[serde(flatten)] span: Span, value: T, - raw: &'a str, + raw: Option<&'a str>, #[serde(skip_serializing_if = "Option::is_none")] bigint: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -34,7 +34,7 @@ impl<'a> From<&BooleanLiteral> for ESTreeLiteral<'a, bool> { Self { span: value.span, value: value.value, - raw: if value.value { "true" } else { "false" }, + raw: Some(if value.value { "true" } else { "false" }), bigint: None, regex: None, } @@ -43,13 +43,25 @@ impl<'a> From<&BooleanLiteral> for ESTreeLiteral<'a, bool> { impl<'a> From<&NullLiteral> for ESTreeLiteral<'a, ()> { fn from(value: &NullLiteral) -> Self { - Self { span: value.span, value: (), raw: "null", bigint: None, regex: None } + Self { span: value.span, value: (), raw: Some("null"), bigint: None, regex: None } } } impl<'a> From<&'a NumericLiteral<'a>> for ESTreeLiteral<'a, f64> { fn from(value: &'a NumericLiteral) -> Self { - Self { span: value.span, value: value.value, raw: value.raw, bigint: None, regex: None } + Self { + span: value.span, + value: value.value, + raw: Some(value.raw), + bigint: None, + regex: None, + } + } +} + +impl<'a> From<&'a StringLiteral<'a>> for ESTreeLiteral<'a, &'a str> { + fn from(value: &'a StringLiteral) -> Self { + Self { span: value.span, value: &value.value, raw: None, bigint: None, regex: None } } } @@ -73,7 +85,7 @@ impl<'a> From<&'a BigIntLiteral<'a>> for ESTreeLiteral<'a, ()> { span: value.span, // BigInts can't be serialized to JSON value: (), - raw: value.raw.as_str(), + raw: Some(value.raw.as_str()), bigint: Some(bigint.to_string()), regex: None, } @@ -94,7 +106,7 @@ impl<'a> From<&'a RegExpLiteral<'a>> for ESTreeLiteral<'a, Option> fn from(value: &'a RegExpLiteral) -> Self { Self { span: value.span, - raw: value.raw, + raw: Some(value.raw), value: match &value.regex.pattern { RegExpPattern::Pattern(_) => Some(EmptyObject {}), _ => None, diff --git a/npm/oxc-types/types.d.ts b/npm/oxc-types/types.d.ts index 99639ea33a354..cab36984c1aa0 100644 --- a/npm/oxc-types/types.d.ts +++ b/npm/oxc-types/types.d.ts @@ -20,8 +20,9 @@ export interface NumericLiteral extends Span { } export interface StringLiteral extends Span { - type: 'StringLiteral'; + type: 'Literal'; value: string; + raw?: undefined; } export interface BigIntLiteral extends Span {