feat(es/ast): Add raw to BigInt (#4218)

This commit is contained in:
Alexander Akait 2022-04-02 09:04:14 +03:00 committed by GitHub
parent 257f0dbb7f
commit e91f271873
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 216 additions and 45 deletions

View File

@ -62,11 +62,22 @@ bridge_lit_from!(Number, usize);
bridge_lit_from!(BigInt, BigIntValue); bridge_lit_from!(BigInt, BigIntValue);
#[ast_node("BigIntLiteral")] #[ast_node("BigIntLiteral")]
#[derive(Eq, Hash, EqIgnoreSpan)] #[derive(Eq, Hash)]
pub struct BigInt { pub struct BigInt {
pub span: Span, pub span: Span,
#[cfg_attr(feature = "rkyv", with(EncodeBigInt))] #[cfg_attr(feature = "rkyv", with(EncodeBigInt))]
pub value: BigIntValue, pub value: BigIntValue,
/// Use `None` value only for transformations to avoid recalculate
/// characters in big integer
#[cfg_attr(feature = "rkyv", with(crate::EncodeJsWord))]
pub raw: Option<JsWord>,
}
impl EqIgnoreSpan for BigInt {
fn eq_ignore_span(&self, other: &Self) -> bool {
self.value == other.value
}
} }
#[cfg(feature = "rkyv")] #[cfg(feature = "rkyv")]
@ -125,8 +136,9 @@ impl<'a> arbitrary::Arbitrary<'a> for BigInt {
fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> { fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
let span = u.arbitrary()?; let span = u.arbitrary()?;
let value = u.arbitrary::<usize>()?.into(); let value = u.arbitrary::<usize>()?.into();
let raw = Some(u.arbitrary::<String>()?.into());
Ok(Self { span, value }) Ok(Self { span, value, raw })
} }
} }
@ -368,6 +380,7 @@ impl From<BigIntValue> for BigInt {
BigInt { BigInt {
span: DUMMY_SP, span: DUMMY_SP,
value, value,
raw: None,
} }
} }
} }

View File

@ -568,8 +568,20 @@ where
fn emit_big_lit(&mut self, v: &BigInt) -> Result { fn emit_big_lit(&mut self, v: &BigInt) -> Result {
self.emit_leading_comments_of_span(v.span, false)?; self.emit_leading_comments_of_span(v.span, false)?;
self.wr.write_lit(v.span, &v.value.to_string())?; if self.cfg.minify {
self.wr.write_lit(v.span, "n")?; self.wr.write_lit(v.span, &v.value.to_string())?;
self.wr.write_lit(v.span, "n")?;
} else {
match &v.raw {
Some(raw) => {
self.wr.write_lit(v.span, raw)?;
}
_ => {
self.wr.write_lit(v.span, &v.value.to_string())?;
self.wr.write_lit(v.span, "n")?;
}
}
}
} }
// fn emit_object_binding_pat(&mut self, node: &ObjectPat) -> Result { // fn emit_object_binding_pat(&mut self, node: &ObjectPat) -> Result {

View File

@ -0,0 +1,14 @@
const n1 = 9007199254740991n;
const n2 = -9007199254740991n;
const n3 = +9007199254740991n;
const n4 = 100_000_000n;
const n5 = 0n;
const n6 = +0n;
const n7 = -0n;
const n8 = 0x10n;
const n9 = 0X10n;
const n10 = 0X10n;
const n11 = 0b101n;
const n12 = 0b101n;
const n13 = 0o13n;
const n14 = 0b101_101n;

View File

@ -0,0 +1,14 @@
const n1 = 9007199254740991n;
const n2 = -9007199254740991n;
const n3 = +9007199254740991n;
const n4 = 100_000_000n;
const n5 = 0n;
const n6 = +0n;
const n7 = -0n;
const n8 = 0x10n;
const n9 = 0X10n;
const n10 = 0X10n;
const n11 = 0b101n;
const n12 = 0b101n;
const n13 = 0o13n;
const n14 = 0b101_101n;

View File

@ -0,0 +1 @@
const n1=9007199254740991n;const n2=-9007199254740991n;const n3=+9007199254740991n;const n4=100000000n;const n5=0n;const n6=+0n;const n7=-0n;const n8=16n;const n9=16n;const n10=16n;const n11=5n;const n12=5n;const n13=11n;const n14=45n

View File

@ -61,3 +61,17 @@ const foo43 = -1000000003242;
const foo43 = 0.0; const foo43 = 0.0;
const foo44 = -0.0; const foo44 = -0.0;
const foo45 = +0.0; const foo45 = +0.0;
const foo46 = 1_000_000_000
const foo47 = 1.1_00_01
const foo48 = 1e1_0
const foo49 = 1e+1_0
const foo50 = 1e-1_0
const foo51 = 1.1e10_0
const foo52 = 1.1e+10_0
const foo53 = 1.1e-10_0
const foo54 = 12_34_56
const foo55 = 1_22_333
const foo56 = 1_2.3_4
const foo57 = 1_2.3_4e5_6
const foo58 = 1_2.3_4e+5_6
const foo59 = 1_2.3_4e-5_6

View File

@ -63,3 +63,17 @@ const foo43 = -1000000003242;
const foo43 = 0; const foo43 = 0;
const foo44 = -0; const foo44 = -0;
const foo45 = +0; const foo45 = +0;
const foo46 = 1000000000;
const foo47 = 1.10001;
const foo48 = 10000000000;
const foo49 = 10000000000;
const foo50 = 0.0000000001;
const foo51 = 11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
const foo52 = 11000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000;
const foo53 = 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011;
const foo54 = 123456;
const foo55 = 122333;
const foo56 = 12.34;
const foo57 = 1234000000000000000000000000000000000000000000000000000000;
const foo58 = 1234000000000000000000000000000000000000000000000000000000;
const foo59 = 0.0000000000000000000000000000000000000000000000000000001234;

View File

@ -1 +1 @@
const exp=1e3;const Exp=1e12;const negativeExp=1e-8;const huge=0xe8d4a51001;const big=100000000001;const fractional=100.23002;const numeric_separators=1e12;const one=1e3;const two=1e6;const three=-1e6;const bin=85;const oct=342391;const hex=3735928559;const fractional2=1000.0001;const identifier=_1000;const negate_identifier=-_1000;const foo=.1;const foo1=+.1;const foo2=-.1;const foo3=1050;const foo4=100500;const foo5=10005e3;const foo6=100005e4;const foo7=.1;const foo8=.01;const foo9=.001;const foo10=1e-4;const foo11=1e-5;const foo12=1e-6;const foo13=24e-6;const foo14=-24e-6;const foo15=10;const foo16=100;const foo17=1e3;const foo18=1e4;const foo19=1e5;const foo20=.1;const foo21=.01;const foo22=.001;const foo23=1e-4;const foo24=1e-5;const foo25=-.1;const foo26=-.01;const foo27=-.001;const foo28=-1e-4;const foo29=-1e-5;const foo30=.001;const foo31=.00321;const foo32=321e-6;const foo33=.1;const foo34=1e-5;const foo35=0;const foo36=-0;const foo37=+0;const foo38=1543e-8;const foo39=1543e-8;const foo40=(1543e-8);const foo41={100005e4:"foo"};const foo42=0xe8d4a51caa;const foo43=-0xe8d4a51caa;const foo43=0;const foo44=-0;const foo45=+0 const exp=1e3;const Exp=1e12;const negativeExp=1e-8;const huge=0xe8d4a51001;const big=100000000001;const fractional=100.23002;const numeric_separators=1e12;const one=1e3;const two=1e6;const three=-1e6;const bin=85;const oct=342391;const hex=3735928559;const fractional2=1000.0001;const identifier=_1000;const negate_identifier=-_1000;const foo=.1;const foo1=+.1;const foo2=-.1;const foo3=1050;const foo4=100500;const foo5=10005e3;const foo6=100005e4;const foo7=.1;const foo8=.01;const foo9=.001;const foo10=1e-4;const foo11=1e-5;const foo12=1e-6;const foo13=24e-6;const foo14=-24e-6;const foo15=10;const foo16=100;const foo17=1e3;const foo18=1e4;const foo19=1e5;const foo20=.1;const foo21=.01;const foo22=.001;const foo23=1e-4;const foo24=1e-5;const foo25=-.1;const foo26=-.01;const foo27=-.001;const foo28=-1e-4;const foo29=-1e-5;const foo30=.001;const foo31=.00321;const foo32=321e-6;const foo33=.1;const foo34=1e-5;const foo35=0;const foo36=-0;const foo37=+0;const foo38=1543e-8;const foo39=1543e-8;const foo40=(1543e-8);const foo41={100005e4:"foo"};const foo42=0xe8d4a51caa;const foo43=-0xe8d4a51caa;const foo43=0;const foo44=-0;const foo45=+0;const foo46=1e9;const foo47=1.10001;const foo48=1e10;const foo49=1e10;const foo50=1e-10;const foo51=11e99;const foo52=11e99;const foo53=11e-101;const foo54=123456;const foo55=122333;const foo56=12.34;const foo57=1234e54;const foo58=1234e54;const foo59=1234e-58

View File

@ -186,7 +186,10 @@ impl<'a, I: Input> Lexer<'a, I> {
.read_number(true) .read_number(true)
.map(|v| match v { .map(|v| match v {
Left(v) => Num(v), Left(v) => Num(v),
Right(v) => BigInt(v), Right((value, raw)) => BigInt {
value,
raw: raw.into(),
},
}) })
.map(Some); .map(Some);
} }
@ -269,7 +272,10 @@ impl<'a, I: Input> Lexer<'a, I> {
.read_number(false) .read_number(false)
.map(|v| match v { .map(|v| match v {
Left(v) => Num(v), Left(v) => Num(v),
Right(v) => BigInt(v), Right((value, raw)) => BigInt {
value,
raw: raw.into(),
},
}) })
.map(Some) .map(Some)
} }
@ -278,16 +284,23 @@ impl<'a, I: Input> Lexer<'a, I> {
return bigint return bigint
.map(|v| match v { .map(|v| match v {
Left(v) => Num(v), Left(v) => Num(v),
Right(v) => BigInt(v), Right((value, raw)) => BigInt {
value,
raw: raw.into(),
},
}) })
.map(Some); .map(Some);
} }
'1'..='9' => { '1'..='9' => {
return self return self
.read_number(false) .read_number(false)
.map(|v| match v { .map(|v| match v {
Left(v) => Num(v), Left(v) => Num(v),
Right(v) => BigInt(v), Right((value, raw)) => BigInt {
value,
raw: raw.into(),
},
}) })
.map(Some) .map(Some)
} }

View File

@ -33,8 +33,9 @@ impl<'a, I: Input> Lexer<'a, I> {
pub(super) fn read_number( pub(super) fn read_number(
&mut self, &mut self,
starts_with_dot: bool, starts_with_dot: bool,
) -> LexResult<Either<f64, BigIntValue>> { ) -> LexResult<Either<f64, (BigIntValue, String)>> {
debug_assert!(self.cur().is_some()); debug_assert!(self.cur().is_some());
if starts_with_dot { if starts_with_dot {
debug_assert_eq!( debug_assert_eq!(
self.cur(), self.cur(),
@ -42,6 +43,7 @@ impl<'a, I: Input> Lexer<'a, I> {
"read_number(starts_with_dot = true) expects current char to be '.'" "read_number(starts_with_dot = true) expects current char to be '.'"
); );
} }
let start = self.cur_pos(); let start = self.cur_pos();
let starts_with_zero = self.cur().unwrap() == '0'; let starts_with_zero = self.cur().unwrap() == '0';
@ -52,14 +54,25 @@ impl<'a, I: Input> Lexer<'a, I> {
0f64 0f64
} else { } else {
// Use read_number_no_dot to support long numbers. // Use read_number_no_dot to support long numbers.
let (val, s, not_octal) = self let (val, s, mut raw, not_octal) = self
.read_number_no_dot_as_str::<10, { lexical::NumberFormatBuilder::from_radix(10) }>( .read_number_no_dot_as_str::<10, { lexical::NumberFormatBuilder::from_radix(10) }>(
)?; )?;
if self.input.cur() == Some('n') {
self.input.bump(); if self.eat(b'n') {
return Ok(Either::Right(s.into_value())); raw.push('n');
return Ok(Either::Right((s.into_value(), raw)));
} }
if self.input.cur() == Some('n') {
raw.push('n');
self.input.bump();
return Ok(Either::Right((s.into_value(), raw)));
}
write!(raw_val, "{}", &s.value).unwrap(); write!(raw_val, "{}", &s.value).unwrap();
if starts_with_zero { if starts_with_zero {
// TODO: I guess it would be okay if I don't use -ffast-math // TODO: I guess it would be okay if I don't use -ffast-math
// (or something like that), but needs review. // (or something like that), but needs review.
@ -117,7 +130,9 @@ impl<'a, I: Input> Lexer<'a, I> {
// `.1.a`, `.1e-4.a` are valid, // `.1.a`, `.1e-4.a` are valid,
if self.cur() == Some('.') { if self.cur() == Some('.') {
raw_val.push('.'); raw_val.push('.');
self.bump(); self.bump();
if starts_with_dot { if starts_with_dot {
debug_assert!(self.cur().is_some()); debug_assert!(self.cur().is_some());
debug_assert!(self.cur().unwrap().is_digit(10)); debug_assert!(self.cur().unwrap().is_digit(10));
@ -126,12 +141,15 @@ impl<'a, I: Input> Lexer<'a, I> {
let mut raw = Raw(Some(String::new())); let mut raw = Raw(Some(String::new()));
// Read numbers after dot // Read numbers after dot
let dec_val = self.read_int::<10>(0, &mut raw)?; let dec_val = self.read_int::<10>(0, &mut raw)?;
val = { val = {
if let Some(..) = dec_val { if let Some(..) = dec_val {
raw_val.push_str(raw.0.as_ref().unwrap()); raw_val.push_str(raw.0.as_ref().unwrap());
} }
raw_val raw_val
// Remove number separator from number
.replace('_', "")
.parse() .parse()
.expect("failed to parse float using rust's impl") .expect("failed to parse float using rust's impl")
}; };
@ -176,7 +194,10 @@ impl<'a, I: Input> Lexer<'a, I> {
write!(raw_val, "{}", exp).unwrap(); write!(raw_val, "{}", exp).unwrap();
// TODO: // TODO:
raw_val.parse().expect("failed to parse float literal") raw_val
.replace('_', "")
.parse()
.expect("failed to parse float literal")
} }
} }
@ -188,7 +209,7 @@ impl<'a, I: Input> Lexer<'a, I> {
/// Returns `Left(value)` or `Right(BigInt)` /// Returns `Left(value)` or `Right(BigInt)`
pub(super) fn read_radix_number<const RADIX: u8, const FORMAT: u128>( pub(super) fn read_radix_number<const RADIX: u8, const FORMAT: u128>(
&mut self, &mut self,
) -> LexResult<Either<f64, BigIntValue>> { ) -> LexResult<Either<f64, (BigIntValue, String)>> {
debug_assert!( debug_assert!(
RADIX == 2 || RADIX == 8 || RADIX == 16, RADIX == 2 || RADIX == 8 || RADIX == 16,
"radix should be one of 2, 8, 16, but got {}", "radix should be one of 2, 8, 16, but got {}",
@ -196,17 +217,36 @@ impl<'a, I: Input> Lexer<'a, I> {
); );
debug_assert_eq!(self.cur(), Some('0')); debug_assert_eq!(self.cur(), Some('0'));
self.bump(); // 0 self.with_buf(|l, buf| {
self.bump(); // x l.bump();
buf.push('0');
let (val, s, _) = self.read_number_no_dot_as_str::<RADIX, FORMAT>()?; let c = match l.input.cur() {
if self.eat(b'n') { Some(c) => {
return Ok(Either::Right(s.into_value())); l.bump();
}
self.ensure_not_ident()?; c
}
_ => {
unreachable!();
}
};
Ok(Either::Left(val)) buf.push(c);
let (val, s, raw, _) = l.read_number_no_dot_as_str::<RADIX, FORMAT>()?;
if l.eat(b'n') {
buf.push_str(&raw);
buf.push('n');
return Ok(Either::Right((s.into_value(), (&**buf).into())));
}
l.ensure_not_ident()?;
Ok(Either::Left(val))
})
} }
/// This can read long integers like /// This can read long integers like
@ -224,6 +264,7 @@ impl<'a, I: Input> Lexer<'a, I> {
let res = self.read_digits::<_, f64, RADIX>( let res = self.read_digits::<_, f64, RADIX>(
|total, radix, v| { |total, radix, v| {
read_any = true; read_any = true;
Ok((f64::mul_add(total, radix as f64, v as f64), true)) Ok((f64::mul_add(total, radix as f64, v as f64), true))
}, },
&mut Raw(None), &mut Raw(None),
@ -243,18 +284,19 @@ impl<'a, I: Input> Lexer<'a, I> {
/// Returned bool is `true` is there was `8` or `9`. /// Returned bool is `true` is there was `8` or `9`.
fn read_number_no_dot_as_str<const RADIX: u8, const FORMAT: u128>( fn read_number_no_dot_as_str<const RADIX: u8, const FORMAT: u128>(
&mut self, &mut self,
) -> LexResult<(f64, LazyBigInt<RADIX>, bool)> { ) -> LexResult<(f64, LazyBigInt<RADIX>, String, bool)> {
debug_assert!( debug_assert!(
RADIX == 2 || RADIX == 8 || RADIX == 10 || RADIX == 16, RADIX == 2 || RADIX == 8 || RADIX == 10 || RADIX == 16,
"radix for read_number_no_dot should be one of 2, 8, 10, 16, but got {}", "radix for read_number_no_dot should be one of 2, 8, 10, 16, but got {}",
RADIX RADIX
); );
let start = self.cur_pos(); let start = self.cur_pos();
let mut non_octal = false;
let mut non_octal = false;
let mut read_any = false; let mut read_any = false;
let mut raw = Raw(Some(String::new())); let mut raw = Raw(Some(String::new()));
self.read_digits::<_, f64, RADIX>( self.read_digits::<_, f64, RADIX>(
|total, radix, v| { |total, radix, v| {
read_any = true; read_any = true;
@ -274,13 +316,17 @@ impl<'a, I: Input> Lexer<'a, I> {
} }
let raw_str = raw.0.take().unwrap(); let raw_str = raw.0.take().unwrap();
// Remove number separator from number
let raw_number_str = raw_str.replace('_', "");
Ok(( Ok((
lexical::parse_with_options::<f64, _, FORMAT>( lexical::parse_with_options::<f64, _, FORMAT>(
raw_str.as_bytes(), raw_number_str.as_bytes(),
&lexical::parse_float_options::Options::from_radix(RADIX), &lexical::parse_float_options::Options::from_radix(RADIX),
) )
.expect("failed to parse float using lexical"), .expect("failed to parse float using lexical"),
LazyBigInt::new(raw_str), LazyBigInt::new(raw_number_str),
raw_str,
non_octal, non_octal,
)) ))
} }
@ -372,22 +418,24 @@ impl<'a, I: Input> Lexer<'a, I> {
"radix for read_int should be one of 2, 8, 10, 16, but got {}", "radix for read_int should be one of 2, 8, 10, 16, but got {}",
RADIX RADIX
); );
if cfg!(feature = "debug") { if cfg!(feature = "debug") {
trace!("read_digits(radix = {}), cur = {:?}", RADIX, self.cur()); trace!("read_digits(radix = {}), cur = {:?}", RADIX, self.cur());
} }
let start = self.cur_pos(); let start = self.cur_pos();
let mut total: Ret = Default::default(); let mut total: Ret = Default::default();
let mut prev = None; let mut prev = None;
while let Some(c) = self.cur() { while let Some(c) = self.cur() {
if allow_num_separator && c == '_' { if allow_num_separator && c == '_' {
let is_allowed = |c: Option<char>| { let is_allowed = |c: Option<char>| {
if c.is_none() { if c.is_none() {
return false; return false;
} }
let c = c.unwrap(); let c = c.unwrap();
c.is_digit(RADIX as _) c.is_digit(RADIX as _)
}; };
let is_forbidden = |c: Option<char>| { let is_forbidden = |c: Option<char>| {
@ -413,6 +461,8 @@ impl<'a, I: Input> Lexer<'a, I> {
// Ignore this _ character // Ignore this _ character
self.input.bump(); self.input.bump();
raw.push(c);
continue; continue;
} }
@ -426,11 +476,15 @@ impl<'a, I: Input> Lexer<'a, I> {
raw.push(c); raw.push(c);
self.bump(); self.bump();
let (t, cont) = op(total, RADIX, val)?; let (t, cont) = op(total, RADIX, val)?;
total = t; total = t;
if !cont { if !cont {
return Ok(total); return Ok(total);
} }
prev = Some(c); prev = Some(c);
} }
@ -612,9 +666,12 @@ mod tests {
"10000000000000000000000000000000000000000000000000000n", "10000000000000000000000000000000000000000000000000000n",
|l| l.read_number(false).unwrap().right().unwrap() |l| l.read_number(false).unwrap().right().unwrap()
), ),
"10000000000000000000000000000000000000000000000000000" (
.parse::<BigIntValue>() "10000000000000000000000000000000000000000000000000000"
.unwrap(), .parse::<BigIntValue>()
.unwrap(),
String::from("10000000000000000000000000000000000000000000000000000n")
),
); );
} }

View File

@ -104,7 +104,7 @@ impl<'a> From<&'a Token> for TokenType {
| Token::Word(Word::Ident(..)) | Token::Word(Word::Ident(..))
| Token::DollarLBrace | Token::DollarLBrace
| Token::Regex(..) | Token::Regex(..)
| Token::BigInt(..) | Token::BigInt { .. }
| Token::JSXText { .. } | Token::JSXText { .. }
| Token::RBrace | Token::RBrace
), ),

View File

@ -317,7 +317,7 @@ impl<'a, I: Tokens> Parser<I> {
| tok!("true") | tok!("true")
| tok!("false") | tok!("false")
| Token::Num(..) | Token::Num(..)
| Token::BigInt(..) | Token::BigInt { .. }
| Token::Str { .. } => { | Token::Str { .. } => {
return Ok(Box::new(Expr::Lit(self.parse_lit()?))); return Ok(Box::new(Expr::Lit(self.parse_lit()?)));
} }
@ -1834,10 +1834,11 @@ impl<'a, I: Tokens> Parser<I> {
}), }),
_ => unreachable!(), _ => unreachable!(),
}, },
Token::BigInt(..) => match bump!(self) { Token::BigInt { .. } => match bump!(self) {
Token::BigInt(value) => Lit::BigInt(BigInt { Token::BigInt { value, raw } => Lit::BigInt(BigInt {
span: span!(self, start), span: span!(self, start),
value, value,
raw: Some(raw),
}), }),
_ => unreachable!(), _ => unreachable!(),
}, },

View File

@ -65,10 +65,11 @@ impl<'a, I: Tokens> Parser<I> {
}), }),
_ => unreachable!(), _ => unreachable!(),
}, },
Token::BigInt(_) => match bump!(p) { Token::BigInt { .. } => match bump!(p) {
Token::BigInt(value) => PropName::BigInt(BigInt { Token::BigInt { value, raw } => PropName::BigInt(BigInt {
span: span!(p, start), span: span!(p, start),
value, value,
raw: Some(raw),
}), }),
_ => unreachable!(), _ => unreachable!(),
}, },

View File

@ -122,7 +122,10 @@ pub enum Token {
Num(f64), Num(f64),
#[kind(starts_expr)] #[kind(starts_expr)]
BigInt(BigIntValue), BigInt {
value: BigIntValue,
raw: JsWord,
},
JSXName { JSXName {
name: JsWord, name: JsWord,
@ -611,7 +614,7 @@ impl Debug for Token {
Str { value, .. } => write!(f, "string literal ({})", value)?, Str { value, .. } => write!(f, "string literal ({})", value)?,
Regex(exp, flags) => write!(f, "regexp literal ({}, {})", exp, flags)?, Regex(exp, flags) => write!(f, "regexp literal ({}, {})", exp, flags)?,
Num(..) => write!(f, "numeric literal")?, Num(..) => write!(f, "numeric literal")?,
BigInt(..) => write!(f, "bigint literal")?, BigInt { .. } => write!(f, "bigint literal")?,
JSXName { name } => write!(f, "jsx name ({})", name)?, JSXName { name } => write!(f, "jsx name ({})", name)?,
JSXText { raw } => write!(f, "jsx text ({})", raw)?, JSXText { raw } => write!(f, "jsx text ({})", raw)?,
JSXTagStart => write!(f, "< (jsx tag start)")?, JSXTagStart => write!(f, "< (jsx tag start)")?,

View File

@ -86,7 +86,8 @@
[ [
1 1
] ]
] ],
"raw": "1n"
} }
} }
], ],

View File

@ -32,7 +32,8 @@
395401161, 395401161,
37 37
] ]
] ],
"raw": "1000000000000000000000000000000000000000000000000000000000000000000000n"
} }
} }
], ],

View File

@ -790,7 +790,9 @@ impl ObjectRest {
}))), }))),
}), }),
), ),
PropName::BigInt(BigInt { span, ref value }) => { PropName::BigInt(BigInt {
span, ref value, ..
}) => {
let value = value.clone(); let value = value.clone();
( (
key, key,
@ -1003,7 +1005,7 @@ fn excluded_props(props: &[ObjectPatProp]) -> Vec<Option<ExprOrSpread>> {
value: format!("{}", value).into(), value: format!("{}", value).into(),
}) })
.as_arg(), .as_arg(),
PropName::BigInt(BigInt { span, value }) => Lit::Str(Str { PropName::BigInt(BigInt { span, value, .. }) => Lit::Str(Str {
span: *span, span: *span,
raw: None, raw: None,
value: format!("{}", value).into(), value: format!("{}", value).into(),

View File

@ -986,6 +986,7 @@ define!({
pub struct BigInt { pub struct BigInt {
pub span: Span, pub span: Span,
pub value: BigIntValue, pub value: BigIntValue,
pub raw: Option<JsWord>,
} }
pub struct Str { pub struct Str {
pub span: Span, pub span: Span,

View File

@ -317,6 +317,8 @@ pub struct BigIntLiteral {
pub base: BaseNode, pub base: BaseNode,
#[serde(default)] #[serde(default)]
pub value: String, pub value: String,
#[serde(default)]
pub raw: JsWord,
} }
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]

View File

@ -84,6 +84,11 @@ impl Babelify for BigInt {
BigIntLiteral { BigIntLiteral {
base: ctx.base(self.span), base: ctx.base(self.span),
value: self.value.to_string(), value: self.value.to_string(),
// TODO improve me
raw: match self.raw {
Some(value) => value,
_ => "".into(),
},
} }
} }
} }

View File

@ -138,6 +138,8 @@ impl Swcify for BigIntLiteral {
.value .value
.parse() .parse()
.expect("failed to parse the value of BigIntLiteral"), .expect("failed to parse the value of BigIntLiteral"),
// TODO improve me
raw: None,
} }
} }
} }