Skip to content

Commit

Permalink
fix(es/minifier): Fix evaluation of -0 as a string (#9011)
Browse files Browse the repository at this point in the history
**Related issue:**

 - Closes #9010

---------

Co-authored-by: magic-akari <akari.ccino@gmail.com>
  • Loading branch information
kdy1 and magic-akari committed Jun 2, 2024
1 parent 1f911f9 commit 9f8e24a
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 12 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions crates/swc_ecma_minifier/src/compress/pure/evaluate.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use radix_fmt::Radix;
use swc_common::{util::take::Take, Spanned, SyntaxContext};
use swc_ecma_ast::*;
use swc_ecma_utils::{undefined, ExprExt, IsEmpty, Value};
use swc_ecma_utils::{number::ToJsString, undefined, ExprExt, IsEmpty, Value};

use super::Pure;
use crate::compress::util::{eval_as_number, is_pure_undefined_or_null};
Expand Down Expand Up @@ -382,7 +382,7 @@ impl Pure<'_> {
if args.first().is_none() {
// https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-number.prototype.toprecision
// 2. If precision is undefined, return ! ToString(x).
let value = ryu_js::Buffer::new().format(num.value).to_string().into();
let value = num.value.to_js_string().into();

self.changed = true;
report_change!(
Expand Down Expand Up @@ -478,7 +478,7 @@ impl Pure<'_> {
.map_or(Some(10f64), |arg| eval_as_number(&self.expr_ctx, &arg.expr))
{
if base.trunc() == 10. {
let value = ryu_js::Buffer::new().format(num.value).to_string().into();
let value = num.value.to_js_string().into();
*e = Expr::Lit(Lit::Str(Str {
span: e.span(),
raw: None,
Expand Down
9 changes: 9 additions & 0 deletions crates/swc_ecma_minifier/tests/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11316,3 +11316,12 @@ fn issue_8982_2() {
",
);
}

#[test]
fn issue_9010() {
run_default_exec_test(
r#"
console.log(-0 + [])
"#,
);
}
10 changes: 4 additions & 6 deletions crates/swc_ecma_transforms_typescript/src/ts_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::mem;
use swc_atoms::JsWord;
use swc_common::{collections::AHashMap, Mark, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_utils::{undefined, ExprFactory};
use swc_ecma_utils::{number::ToJsString, undefined, ExprFactory};
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -207,14 +207,12 @@ impl<'a> EnumValueComputer<'a> {
TsEnumRecordValue::String(format!("{}{}", left, right).into())
}
(TsEnumRecordValue::Number(left), TsEnumRecordValue::String(right), op!(bin, "+")) => {
let mut buffer = ryu_js::Buffer::new();
let left = buffer.format(left);
let left = left.to_js_string();

TsEnumRecordValue::String(format!("{}{}", left, right).into())
}
(TsEnumRecordValue::String(left), TsEnumRecordValue::Number(right), op!(bin, "+")) => {
let mut buffer = ryu_js::Buffer::new();
let right = buffer.format(right);
let right = right.to_js_string();

TsEnumRecordValue::String(format!("{}{}", left, right).into())
}
Expand Down Expand Up @@ -279,7 +277,7 @@ impl<'a> EnumValueComputer<'a> {

let expr = match expr {
TsEnumRecordValue::String(s) => s.to_string(),
TsEnumRecordValue::Number(n) => ryu_js::Buffer::new().format(n).to_string(),
TsEnumRecordValue::Number(n) => n.to_js_string(),
_ => return opaque_expr,
};

Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ num_cpus = { workspace = true }
once_cell = { workspace = true }
rayon = { workspace = true, optional = true }
rustc-hash = { workspace = true }
ryu-js = { workspace = true }
tracing = { workspace = true }
unicode-id = { workspace = true }

Expand Down
10 changes: 9 additions & 1 deletion crates/swc_ecma_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub extern crate swc_common;

use std::{borrow::Cow, hash::Hash, num::FpCategory, ops::Add};

use number::ToJsString;
use rustc_hash::FxHashMap;
use swc_atoms::JsWord;
use swc_common::{
Expand Down Expand Up @@ -50,6 +51,7 @@ mod value;
pub mod var;

mod node_ignore_span;
pub mod number;
pub mod stack_size;
pub use node_ignore_span::NodeIgnoringSpan;

Expand Down Expand Up @@ -979,7 +981,13 @@ pub trait ExprExt {
match *expr {
Expr::Lit(ref l) => match *l {
Lit::Str(Str { ref value, .. }) => Known(Cow::Borrowed(value)),
Lit::Num(ref n) => Known(format!("{}", n).into()),
Lit::Num(ref n) => {
if n.value == -0.0 {
return Known(Cow::Borrowed("0"));
}

Known(Cow::Owned(n.value.to_js_string()))
}
Lit::Bool(Bool { value: true, .. }) => Known(Cow::Borrowed("true")),
Lit::Bool(Bool { value: false, .. }) => Known(Cow::Borrowed("false")),
Lit::Null(..) => Known(Cow::Borrowed("null")),
Expand Down
11 changes: 11 additions & 0 deletions crates/swc_ecma_utils/src/number.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// <https://tc39.es/ecma262/#sec-numeric-types-number-tostring>
pub trait ToJsString {
fn to_js_string(&self) -> String;
}

impl ToJsString for f64 {
fn to_js_string(&self) -> String {
let mut buffer = ryu_js::Buffer::new();
buffer.format(*self).to_string()
}
}

0 comments on commit 9f8e24a

Please sign in to comment.