mirror of
https://github.com/swc-project/swc.git
synced 2024-11-24 10:12:42 +03:00
fix(es/ast): Fix json deserialization of AssignExpr
(#5179)
This commit is contained in:
parent
65595830f3
commit
53627aff44
@ -1,6 +1,10 @@
|
||||
#![allow(clippy::vec_box)]
|
||||
use is_macro::Is;
|
||||
use serde::{self, Deserialize, Serialize};
|
||||
use serde::{
|
||||
self,
|
||||
de::{self, MapAccess, Visitor},
|
||||
Deserialize, Deserializer, Serialize,
|
||||
};
|
||||
use string_enum::StringEnum;
|
||||
use swc_atoms::Atom;
|
||||
use swc_common::{ast_node, util::take::Take, BytePos, EqIgnoreSpan, Span, Spanned, DUMMY_SP};
|
||||
@ -446,7 +450,24 @@ impl Take for ClassExpr {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[ast_node("AssignmentExpression")]
|
||||
|
||||
#[derive(Spanned, Clone, Debug, PartialEq, Serialize)]
|
||||
#[cfg_attr(
|
||||
feature = "rkyv",
|
||||
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
|
||||
)]
|
||||
#[cfg_attr(
|
||||
feature = "rkyv",
|
||||
archive(bound(
|
||||
serialize = "__S: rkyv::ser::Serializer + rkyv::ser::ScratchSpace + \
|
||||
rkyv::ser::SharedSerializeRegistry",
|
||||
deserialize = "__D: rkyv::de::SharedDeserializeRegistry"
|
||||
))
|
||||
)]
|
||||
#[cfg_attr(feature = "rkyv", archive_attr(repr(C), derive(bytecheck::CheckBytes)))]
|
||||
#[serde(tag = "type")]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(rename = "AssignmentExpression")]
|
||||
#[derive(Eq, Hash, EqIgnoreSpan)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
pub struct AssignExpr {
|
||||
@ -471,6 +492,91 @@ impl Take for AssignExpr {
|
||||
}
|
||||
}
|
||||
|
||||
// Custom deserializer to convert `PatOrExpr::Pat(Box<Pat::Ident>)`
|
||||
// to `PatOrExpr::Expr(Box<Expr::Ident>)` when `op` is not `=`.
|
||||
// Same logic as parser:
|
||||
// https://github.com/swc-project/swc/blob/b87e3b0d4f46e6aea1ee7745f0bb3d129ef12b9c/crates/swc_ecma_parser/src/parser/pat.rs#L602-L610
|
||||
impl<'de> Deserialize<'de> for AssignExpr {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct AssignExprVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for AssignExprVisitor {
|
||||
type Value = AssignExpr;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
formatter.write_str("struct AssignExpr")
|
||||
}
|
||||
|
||||
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
|
||||
where
|
||||
M: MapAccess<'de>,
|
||||
{
|
||||
let mut span_field: Option<Span> = None;
|
||||
let mut op_field: Option<AssignOp> = None;
|
||||
let mut left_field: Option<PatOrExpr> = None;
|
||||
let mut right_field: Option<Box<Expr>> = None;
|
||||
|
||||
while let Some(key) = map.next_key()? {
|
||||
match key {
|
||||
"span" => {
|
||||
if span_field.is_some() {
|
||||
return Err(de::Error::duplicate_field("span"));
|
||||
}
|
||||
span_field = Some(map.next_value()?);
|
||||
}
|
||||
"operator" => {
|
||||
if op_field.is_some() {
|
||||
return Err(de::Error::duplicate_field("operator"));
|
||||
}
|
||||
op_field = Some(map.next_value()?);
|
||||
}
|
||||
"left" => {
|
||||
if left_field.is_some() {
|
||||
return Err(de::Error::duplicate_field("left"));
|
||||
}
|
||||
left_field = Some(map.next_value()?);
|
||||
}
|
||||
"right" => {
|
||||
if right_field.is_some() {
|
||||
return Err(de::Error::duplicate_field("right"));
|
||||
}
|
||||
right_field = Some(map.next_value()?);
|
||||
}
|
||||
_ => {
|
||||
let _: de::IgnoredAny = map.next_value()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let span = span_field.ok_or_else(|| de::Error::missing_field("span"))?;
|
||||
let op = op_field.ok_or_else(|| de::Error::missing_field("operator"))?;
|
||||
let mut left = left_field.ok_or_else(|| de::Error::missing_field("left"))?;
|
||||
let right = right_field.ok_or_else(|| de::Error::missing_field("right"))?;
|
||||
|
||||
if op != AssignOp::Assign {
|
||||
if let PatOrExpr::Pat(ref pat) = left {
|
||||
if let Pat::Ident(ident) = &**pat {
|
||||
left = PatOrExpr::Expr(Box::new(Expr::Ident(ident.id.clone())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(AssignExpr {
|
||||
span,
|
||||
op,
|
||||
left,
|
||||
right,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_map(AssignExprVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[ast_node("MemberExpression")]
|
||||
#[derive(Eq, Hash, EqIgnoreSpan)]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
|
Loading…
Reference in New Issue
Block a user