diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 41ffbd4df5c..19d74390d57 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -1,6 +1,6 @@
name: Lint
-on: [push]
+on: [push, pull_request]
jobs:
lint:
diff --git a/ecmascript/codegen/tests/references/15a12468ff312d51.js b/ecmascript/codegen/tests/references/15a12468ff312d51.js
index af1aad6c18e..4c94075c1e1 100644
--- a/ecmascript/codegen/tests/references/15a12468ff312d51.js
+++ b/ecmascript/codegen/tests/references/15a12468ff312d51.js
@@ -1 +1 @@
-622141790000000000000000;
+602214179000000000000000;
diff --git a/ecmascript/parser/src/lexer/number.rs b/ecmascript/parser/src/lexer/number.rs
index 6641e0713d5..3f510ef843e 100644
--- a/ecmascript/parser/src/lexer/number.rs
+++ b/ecmascript/parser/src/lexer/number.rs
@@ -87,13 +87,14 @@ impl<'a, I: Input> Lexer<'a, I> {
debug_assert!(self.cur().unwrap().is_digit(10));
}
+ let mut raw = Raw(Some(String::new()));
// Read numbers after dot
- let dec_val = self.read_int(10, 0, &mut Raw(None))?;
+ let dec_val = self.read_int(10, 0, &mut raw)?;
let mut s = String::new();
write!(s, "{}.", val).unwrap();
- if let Some(ref n) = dec_val {
- write!(s, "{}", n).unwrap();
+ if let Some(..) = dec_val {
+ s.push_str(&raw.0.as_ref().unwrap());
}
val = s.parse().expect("failed to parse float using rust's impl");
@@ -402,6 +403,11 @@ mod tests {
debug_assert_eq!(77777777777777777.1f64, num("77777777777777777.1"))
}
+ #[test]
+ fn issue_480() {
+ debug_assert_eq!(9.09, num("9.09"))
+ }
+
#[test]
fn num_legacy_octal() {
debug_assert_eq!(0o12 as f64, num("0012"));
diff --git a/ecmascript/parser/src/lexer/tests.rs b/ecmascript/parser/src/lexer/tests.rs
index 7a3dcdf9aa7..b490d5c7a04 100644
--- a/ecmascript/parser/src/lexer/tests.rs
+++ b/ecmascript/parser/src/lexer/tests.rs
@@ -1088,6 +1088,36 @@ fn issue_401() {
);
}
+#[test]
+fn issue_481() {
+ assert_eq!(
+ lex_tokens(
+ crate::Syntax::Es(crate::EsConfig {
+ jsx: true,
+ ..Default::default()
+ }),
+ " {foo}"
+ ),
+ vec![
+ Token::JSXTagStart,
+ Token::JSXName {
+ name: "span".into()
+ },
+ Token::JSXTagEnd,
+ JSXText { raw: " ".into() },
+ LBrace,
+ Word(Word::Ident("foo".into())),
+ RBrace,
+ JSXTagStart,
+ BinOp(Div),
+ JSXName {
+ name: "span".into()
+ },
+ JSXTagEnd,
+ ]
+ );
+}
+
#[bench]
fn lex_colors_js(b: &mut Bencher) {
b.bytes = include_str!("../../colors.js").len() as _;
diff --git a/ecmascript/transforms/src/modules/amd.rs b/ecmascript/transforms/src/modules/amd.rs
index fcb251aa037..b3157490006 100644
--- a/ecmascript/transforms/src/modules/amd.rs
+++ b/ecmascript/transforms/src/modules/amd.rs
@@ -7,7 +7,7 @@ use crate::{
util::{prepend_stmts, var::VarCollector, DestructuringFinder, ExprFactory},
};
use ast::*;
-use hashbrown::HashSet;
+use fxhash::FxHashSet;
use serde::{Deserialize, Serialize};
use std::iter;
use swc_atoms::js_word;
@@ -55,7 +55,7 @@ impl Fold for Amd {
}
let mut exports = vec![];
- let mut initialized = HashSet::default();
+ let mut initialized = FxHashSet::default();
let mut export_alls = vec![];
let mut emitted_esmodule = false;
let mut has_export = false;
diff --git a/ecmascript/transforms/src/modules/common_js.rs b/ecmascript/transforms/src/modules/common_js.rs
index e712c689816..e487dd53c22 100644
--- a/ecmascript/transforms/src/modules/common_js.rs
+++ b/ecmascript/transforms/src/modules/common_js.rs
@@ -8,7 +8,7 @@ use crate::{
util::{var::VarCollector, DestructuringFinder, ExprFactory},
};
use ast::*;
-use hashbrown::HashSet;
+use fxhash::FxHashSet;
use swc_atoms::js_word;
use swc_common::{Fold, FoldWith, VisitWith, DUMMY_SP};
@@ -40,7 +40,7 @@ impl Fold> for CommonJs {
}
let mut exports = vec![];
- let mut initialized = HashSet::default();
+ let mut initialized = FxHashSet::default();
let mut export_alls = vec![];
for item in items {
diff --git a/ecmascript/transforms/src/modules/umd.rs b/ecmascript/transforms/src/modules/umd.rs
index 7878d9d986d..6aef2bcf2d6 100644
--- a/ecmascript/transforms/src/modules/umd.rs
+++ b/ecmascript/transforms/src/modules/umd.rs
@@ -9,7 +9,7 @@ use crate::{
util::{prepend_stmts, var::VarCollector, DestructuringFinder, ExprFactory},
};
use ast::*;
-use hashbrown::HashSet;
+use fxhash::FxHashSet;
use std::sync::Arc;
use swc_atoms::js_word;
use swc_common::{Fold, FoldWith, Mark, SourceMap, VisitWith, DUMMY_SP};
@@ -53,7 +53,7 @@ impl Fold for Umd {
}
let mut exports = vec![];
- let mut initialized = HashSet::default();
+ let mut initialized = FxHashSet::default();
let mut export_alls = vec![];
let mut emitted_esmodule = false;
let mut has_export = false;
diff --git a/ecmascript/transforms/src/modules/util.rs b/ecmascript/transforms/src/modules/util.rs
index 6888de94200..6b25ec8aaf4 100644
--- a/ecmascript/transforms/src/modules/util.rs
+++ b/ecmascript/transforms/src/modules/util.rs
@@ -1,5 +1,6 @@
use crate::util::{undefined, DestructuringFinder, ExprFactory};
use ast::*;
+use fxhash::FxHashSet;
use hashbrown::{hash_map::Entry, HashMap, HashSet};
use indexmap::IndexMap;
use inflector::Inflector;
@@ -718,7 +719,7 @@ pub(super) fn use_strict() -> Stmt {
/// ```js
/// exports.default = exports.foo = void 0;
/// ```
-pub(super) fn initialize_to_undefined(exports: Ident, initialized: HashSet) -> Box {
+pub(super) fn initialize_to_undefined(exports: Ident, initialized: FxHashSet) -> Box {
let mut rhs = undefined(DUMMY_SP);
for name in initialized.into_iter() {
diff --git a/ecmascript/transforms/src/react/jsx.rs b/ecmascript/transforms/src/react/jsx.rs
index a20b95d2d21..b90805c946c 100644
--- a/ecmascript/transforms/src/react/jsx.rs
+++ b/ecmascript/transforms/src/react/jsx.rs
@@ -172,6 +172,7 @@ impl Jsx {
if s.value.is_empty() {
return None;
}
+
Lit::Str(s).as_arg()
}
JSXElementChild::JSXExprContainer(JSXExprContainer {
@@ -392,11 +393,14 @@ fn to_prop_name(n: JSXAttrName) -> PropName {
}
fn jsx_text_to_str(t: JsWord) -> JsWord {
+ if t == *" " {
+ return t;
+ }
if !t.contains(' ') && !t.contains('\n') {
return t;
}
- let mut buf = String::new();
+ let mut buf = String::from("");
for s in t.replace("\n", " ").split_ascii_whitespace() {
buf.push_str(s);
buf.push(' ');
diff --git a/ecmascript/transforms/src/react/jsx/tests.rs b/ecmascript/transforms/src/react/jsx/tests.rs
index 8a27ee1d6a3..a5878639e58 100644
--- a/ecmascript/transforms/src/react/jsx/tests.rs
+++ b/ecmascript/transforms/src/react/jsx/tests.rs
@@ -1066,3 +1066,17 @@ test!(
var _react = _interopRequireDefault(require('react'));
_react.default.createElement('div', null);"
);
+
+test!(
+ ::swc_ecma_parser::Syntax::Es(::swc_ecma_parser::EsConfig {
+ jsx: true,
+ ..Default::default()
+ }),
+ |_| tr(Options {
+ use_builtins: true,
+ ..Default::default()
+ }),
+ issue_481,
+ " {foo};",
+ "React.createElement('span', null, ' ', foo);"
+);