Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update swc #32210

Merged
merged 45 commits into from Dec 8, 2021
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
9991358
Update crates
kdy1 Dec 7, 2021
2232a50
Update deps
kdy1 Dec 7, 2021
f0d6e40
Fix js handler
kdy1 Dec 7, 2021
2f54305
Update code for js
kdy1 Dec 7, 2021
c76cc38
DEBUG
kdy1 Dec 7, 2021
2284654
Fix index
kdy1 Dec 7, 2021
d52f3e3
Prevent panic
kdy1 Dec 7, 2021
65d6d09
Skip some spaces
kdy1 Dec 7, 2021
f8cdf22
Log
kdy1 Dec 7, 2021
c8fb5ec
More fix
kdy1 Dec 7, 2021
c08a40d
Logging
kdy1 Dec 7, 2021
7c67c3a
Remove `dbg!`
kdy1 Dec 7, 2021
2f152a8
Fix prefixer
kdy1 Dec 7, 2021
6d57e20
Remove wrong logic
kdy1 Dec 7, 2021
3f9a734
Update test refs (hygiene)
kdy1 Dec 7, 2021
acb8e8c
Update swc
kdy1 Dec 7, 2021
99c6afc
Update test refs
kdy1 Dec 7, 2021
5395085
Update test refs
kdy1 Dec 7, 2021
218e13c
Update test refs
kdy1 Dec 7, 2021
77d9fe3
Update test refs
kdy1 Dec 7, 2021
a16a1dd
Update test refs
kdy1 Dec 7, 2021
68b0957
Update test refs
kdy1 Dec 7, 2021
2bc25fc
Update test refs
kdy1 Dec 7, 2021
ac8e874
Update test refs
kdy1 Dec 7, 2021
6b62d48
Update test refs
kdy1 Dec 7, 2021
9b9c4f3
Remove hack for prefixer
kdy1 Dec 7, 2021
b31c9c1
Update test refs
kdy1 Dec 7, 2021
7c8a678
Update test refs
kdy1 Dec 7, 2021
7defcf1
Update test refs
kdy1 Dec 7, 2021
7c8defa
Better logging
kdy1 Dec 7, 2021
975e14a
Add test refs
kdy1 Dec 7, 2021
4850822
Update test refs
kdy1 Dec 7, 2021
791ed9a
Update test refs
kdy1 Dec 7, 2021
9822ae8
Update test refs
kdy1 Dec 7, 2021
e99afd1
Improve logging
kdy1 Dec 7, 2021
7ea875a
Doc
kdy1 Dec 7, 2021
04bcbc3
Fix
kdy1 Dec 7, 2021
7fa2f90
Update test refs
kdy1 Dec 7, 2021
03256bd
Update test refs
kdy1 Dec 7, 2021
964bbe4
Update `swc`
kdy1 Dec 8, 2021
e47af03
Update test refs
kdy1 Dec 8, 2021
885b49a
Merge branch 'canary' into update-swc-min
kdy1 Dec 8, 2021
6ca31c6
Update `swc_ecma_transforms_compat`
kdy1 Dec 8, 2021
34ad44b
Merge branch 'canary' into update-swc-min
kdy1 Dec 8, 2021
5e3ef5b
Fix test whitespace
timneutkens Dec 8, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
219 changes: 132 additions & 87 deletions packages/next-swc/Cargo.lock

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions packages/next-swc/crates/core/Cargo.toml
Expand Up @@ -14,21 +14,21 @@ fxhash = "0.2.1"
pathdiff = "0.2.0"
serde = "1"
serde_json = "1"
styled_components = "0.2.0"
swc = "0.88.0"
styled_components = "0.4.0"
swc = "0.94.0"
swc_atoms = "0.2.7"
swc_common = {version = "0.14.2", features = ["concurrent", "sourcemap"]}
swc_css = "0.31.0"
swc_ecma_loader = { version = "0.24.4", features = ["node", "lru"] }
swc_ecmascript = { version = "0.88.2", features = ["codegen", "minifier", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
swc_common = { version = "0.15.0", features = ["concurrent", "sourcemap"] }
swc_css = "0.44.0"
swc_ecma_loader = { version = "0.25.0", features = ["node", "lru"] }
swc_ecmascript = { version = "0.95.0", features = ["codegen", "minifier", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
swc_node_base = "0.5.1"
swc_stylis = "0.28.0"
swc_stylis = "0.41.0"
tracing = {version = "0.1.28", features = ["release_max_level_off"]}
regex = "1.5"

[dev-dependencies]
swc_ecma_transforms_testing = "0.45.1"
testing = "0.15.2"
swc_ecma_transforms_testing = "0.49.0"
testing = "0.16.0"
walkdir = "2.3.2"


11 changes: 5 additions & 6 deletions packages/next-swc/crates/core/src/auto_cjs/mod.rs
@@ -1,12 +1,11 @@
use swc_common::DUMMY_SP;
use swc_ecmascript::{
ast::*,
visit::{Node, Visit, VisitWith},
visit::{Visit, VisitWith},
};

pub(crate) fn contains_cjs(m: &Module) -> bool {
let mut v = CjsFinder::default();
m.visit_with(&Invalid { span: DUMMY_SP }, &mut v);
m.visit_with(&mut v);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a major difference.

v.found
}

Expand All @@ -18,7 +17,7 @@ struct CjsFinder {
/// This visitor implementation supports typescript, because the api of `swc`
/// does not support changing configuration based on content of the file.
impl Visit for CjsFinder {
fn visit_member_expr(&mut self, e: &MemberExpr, _: &dyn Node) {
fn visit_member_expr(&mut self, e: &MemberExpr) {
if !e.computed {
match &e.obj {
ExprOrSuper::Super(_) => {}
Expand All @@ -37,10 +36,10 @@ impl Visit for CjsFinder {
}
}

e.obj.visit_with(e, self);
e.obj.visit_with(self);

if e.computed {
e.prop.visit_with(e, self);
e.prop.visit_with(self);
}
}
}
247 changes: 165 additions & 82 deletions packages/next-swc/crates/core/src/styled_jsx/transform_css.rs
@@ -1,5 +1,6 @@
use easy_error::{bail, Error};
use std::panic;
use swc_common::util::take::Take;
use swc_common::{source_map::Pos, BytePos, Span, SyntaxContext, DUMMY_SP};
use swc_css::ast::*;
use swc_css::codegen::{
Expand All @@ -11,6 +12,7 @@ use swc_css::visit::{VisitMut, VisitMutWith};
use swc_ecmascript::ast::{Expr, Str, StrKind, Tpl, TplElement};
use swc_ecmascript::utils::HANDLER;
use swc_stylis::prefixer::prefixer;
use tracing::{debug, trace};

use super::{hash_string, string_literal_expr, LocalStyle};

Expand All @@ -19,6 +21,8 @@ pub fn transform_css(
is_global: bool,
class_name: &Option<String>,
) -> Result<Expr, Error> {
debug!("CSS: \n{}", style_info.css);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This expression (and corresponding expression statement) will be completely noop on release builds.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @padmaia
It was useful for debugging to me, but I'm not sure if it's good to have this line.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand what it does. Doesn't seem to be spamming the terminal by default so I think I'm okay with it, but it would help to understand how it works.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We enable release_max_level_off of tracing, which is a crate for logging.
The cargo feature release_max_level_off removes all logging for release build and all macro calls for logging become completely no-op.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logging statement will print the input passed to the css parser while testing.
testing is a crate for testing swc crates and next-swc, and it configures logger by default.

Logging level is debug by default, but if you run it like RUST_LOG=trace cargo test, trace! calls will also print the messages.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a side note, tracing is used by swc and rustc.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image


let result: Result<Stylesheet, _> = parse_str(
&style_info.css,
style_info.css_span.lo,
Expand Down Expand Up @@ -52,8 +56,8 @@ pub fn transform_css(
}
};
// ? Do we need to support optionally prefixing?
ss.visit_mut_with(&mut FixedPrefixer);
ss.visit_mut_with(&mut CssFixer);
ss.visit_mut_with(&mut prefixer());
ss.visit_mut_with(&mut CssPlaceholderFixer);
ss.visit_mut_with(&mut Namespacer {
class_name: match class_name {
Some(s) => s.clone(),
Expand Down Expand Up @@ -122,27 +126,17 @@ fn read_number(s: &str) -> (usize, usize) {
unreachable!("read_number(`{}`) is invalid because it is empty", s)
}

/// Applies `prefixer`, but this avoids bug of `swc_stylis::prefixer()`.
/// This fixes invalid css which is created from interpolated expressions.
///
/// TODO(kdy1): Remove this when we upgrade crates related to css. (The crate
/// update is blocked by `ComplexSelectorChildren` issue)
struct FixedPrefixer;

impl VisitMut for FixedPrefixer {
fn visit_mut_style_rule(&mut self, n: &mut StyleRule) {
n.visit_mut_with(&mut prefixer());
}
}

/// This fixes invalid css.
struct CssFixer;
/// `__styled-jsx-placeholder-` is handled at here.
struct CssPlaceholderFixer;

impl VisitMut for CssFixer {
impl VisitMut for CssPlaceholderFixer {
fn visit_mut_media_query(&mut self, q: &mut MediaQuery) {
q.visit_mut_children_with(self);

match q {
MediaQuery::Text(q) => {
MediaQuery::Ident(q) => {
if q.raw.starts_with("__styled-jsx-placeholder-") {
// TODO(kdy1): Remove this once we have CST for media query.
// We need good error recovery for media queries to handle this.
Expand All @@ -162,88 +156,177 @@ struct Namespacer {

impl VisitMut for Namespacer {
fn visit_mut_complex_selector(&mut self, node: &mut ComplexSelector) {
#[cfg(debug_assertions)]
let _tracing = {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block explictly uses #[cfg(debug_assertions)] because it does some operation which cannot removed by tracing.

// This will add information to the log messages, only for debug build.
// Note that we use cargo feature to remove all logging on production builds.

let mut code = String::new();
{
let mut wr = BasicCssWriter::new(&mut code, BasicCssWriterConfig { indent: " " });
let mut gen = CodeGenerator::new(&mut wr, CodegenConfig { minify: true });

gen.emit(&*node).unwrap();
}

tracing::span!(
tracing::Level::TRACE,
"Namespacer::visit_mut_complex_selector",
class_name = &*self.class_name,
is_global = self.is_global,
is_dynamic = self.is_dynamic,
input = &*code
)
.entered()
};

let mut new_selectors = vec![];
for selector in &node.selectors {
match self.get_transformed_selectors(selector.clone()) {
Ok(transformed_selectors) => new_selectors.extend(transformed_selectors),
Err(_) => {
HANDLER.with(|handler| {
handler
.struct_span_err(
selector.span,
"Failed to transform one off global selector",
)
.emit()
});
new_selectors.push(selector.clone());
let mut combinator = None;
for sel in node.children.take() {
match &sel {
ComplexSelectorChildren::CompoundSelector(selector) => {
match self.get_transformed_selectors(combinator, selector.clone()) {
Ok(transformed_selectors) => new_selectors.extend(transformed_selectors),
Err(_) => {
HANDLER.with(|handler| {
handler
.struct_span_err(
selector.span,
"Failed to transform one off global selector",
)
.emit()
});
new_selectors.push(sel);
}
}

combinator = None;
}
ComplexSelectorChildren::Combinator(v) => match v.value {
CombinatorValue::Descendant => {}
CombinatorValue::NextSibling
| CombinatorValue::Child
| CombinatorValue::LaterSibling => {
combinator = Some(v.clone());

new_selectors.push(sel);
}
},
};
}
node.selectors = new_selectors;
node.children = new_selectors;
}
}

impl Namespacer {
fn get_transformed_selectors(
&mut self,
combinator: Option<Combinator>,
mut node: CompoundSelector,
) -> Result<Vec<CompoundSelector>, Error> {
) -> Result<Vec<ComplexSelectorChildren>, Error> {
let mut pseudo_index = None;

let empty_tokens = Tokens {
span: node.span,
tokens: vec![],
};

for (i, selector) in node.subclass_selectors.iter().enumerate() {
if let SubclassSelector::Pseudo(PseudoSelector { name, args, .. }) = selector {
// One off global selector
if &name.value == "global" {
let block_tokens = get_block_tokens(&args);
let mut front_tokens = get_front_selector_tokens(&args);
let mut args = args.clone();
front_tokens.extend(args.tokens);
front_tokens.extend(block_tokens);
args.tokens = front_tokens;
let complex_selectors = panic::catch_unwind(|| {
let x: ComplexSelector = parse_tokens(
&args,
ParserConfig {
parse_values: false,
allow_wrong_line_comments: true,
},
// TODO(kdy1): We might be able to report syntax errors.
&mut vec![],
)
.unwrap();
return x;
});

return match complex_selectors {
Ok(complex_selectors) => {
let mut v = complex_selectors.selectors[1..]
.iter()
.cloned()
.collect::<Vec<_>>();

if v.is_empty() {
bail!("Failed to transform one off global selector");
let (name, args) = match selector {
SubclassSelector::PseudoClass(PseudoClassSelector { name, children, .. }) => {
match children {
Some(PseudoSelectorChildren::Nth(_)) => todo!("nth"),
Some(PseudoSelectorChildren::Tokens(v)) => (name, v),
None => (name, &empty_tokens),
}
}
SubclassSelector::PseudoElement(PseudoElementSelector {
name, children, ..
}) => match children {
Some(children) => (name, children),
None => (name, &empty_tokens),
},
_ => continue,
};

// One off global selector
if &name.value == "global" {
let block_tokens = get_block_tokens(&args);
let mut front_tokens = get_front_selector_tokens(&args);
let mut args = args.clone();
front_tokens.extend(args.tokens);
front_tokens.extend(block_tokens);
args.tokens = front_tokens;

let complex_selectors = panic::catch_unwind(|| {
let x: ComplexSelector = parse_tokens(
&args,
ParserConfig {
parse_values: false,
allow_wrong_line_comments: true,
},
// TODO(kdy1): We might be able to report syntax errors.
&mut vec![],
)
.unwrap();
return x;
});

return match complex_selectors {
Ok(complex_selectors) => {
let mut v = complex_selectors.children[1..]
.iter()
.cloned()
.collect::<Vec<_>>();

match v[0] {
ComplexSelectorChildren::Combinator(Combinator {
value: CombinatorValue::Descendant,
..
}) => {
v.remove(0);
}
_ => {}
}

if node.combinator.is_some() && v[0].combinator.is_some() {
bail!("Failed to transform one off global selector");
} else if node.combinator.is_some() {
v[0].combinator = node.combinator;
if v.is_empty() {
bail!("Failed to transform one off global selector");
}

trace!("Combinator: {:?}", combinator);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @padmaia
This line is also removable. I used it to debug styled-jsx, but I'm not sure if it's better to remove it.
Also completely noop on release builds.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same answer as the debug comment

trace!("v[0]: {:?}", v[0]);

if combinator.is_some() {
match v.get(0) {
Some(ComplexSelectorChildren::Combinator(..)) => {}
Some(..) => {}
_ => {
v.push(ComplexSelectorChildren::Combinator(
combinator.unwrap(),
));
}
}
}

v.iter_mut().for_each(|sel| {
if i < node.subclass_selectors.len() {
sel.subclass_selectors
.extend(node.subclass_selectors[i + 1..].to_vec());
v.iter_mut().for_each(|sel| {
if i < node.subclass_selectors.len() {
match sel {
ComplexSelectorChildren::CompoundSelector(sel) => {
sel.subclass_selectors.extend(
node.subclass_selectors[i + 1..].iter().cloned(),
);
}
_ => {}
}
});
}
});

Ok(v)
}
Err(_) => bail!("Failed to transform one off global selector"),
};
} else if pseudo_index.is_none() {
pseudo_index = Some(i);
}
Ok(v)
}
Err(_) => bail!("Failed to transform one off global selector"),
};
} else if pseudo_index.is_none() {
pseudo_index = Some(i);
}
}

Expand All @@ -260,7 +343,7 @@ impl Namespacer {
insert_index,
SubclassSelector::Class(ClassSelector {
span: DUMMY_SP,
text: Text {
text: Ident {
raw: subclass_selector.into(),
value: subclass_selector.into(),
span: DUMMY_SP,
Expand All @@ -269,7 +352,7 @@ impl Namespacer {
);
}

Ok(vec![node])
Ok(vec![ComplexSelectorChildren::CompoundSelector(node)])
}
}

Expand Down