Skip to content

Commit

Permalink
Revert "Update swc_core to v0.83.26 (#55780)"
Browse files Browse the repository at this point in the history
This reverts commit 81d2926.
  • Loading branch information
sokra committed Sep 27, 2023
1 parent 81d2926 commit fefb27f
Show file tree
Hide file tree
Showing 20 changed files with 626 additions and 142 deletions.
197 changes: 83 additions & 114 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,18 @@ next-transform-dynamic = { path = "packages/next-swc/crates/next-transform-dynam
next-transform-strip-page-exports = { path = "packages/next-swc/crates/next-transform-strip-page-exports" }

# SWC crates
swc_core = { version = "0.83.26", features = [
swc_core = { version = "0.83.12", features = [
"ecma_loader_lru",
"ecma_loader_parking_lot",
] }
testing = { version = "0.34.1" }

# Turbo crates
turbopack-binding = { git = "https://github.com/vercel/turbo.git", branch = "kdy1/swc-transforms" } # last tag: "turbopack-230922.3"
turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230922.3" }
# [TODO]: need to refactor embed_directory! macro usages, as well as resolving turbo_tasks::function, macros..
turbo-tasks = { git = "https://github.com/vercel/turbo.git", branch = "kdy1/swc-transforms" } # last tag: "turbopack-230922.3"
turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230922.3" }
# [TODO]: need to refactor embed_directory! macro usage in next-core
turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", branch = "kdy1/swc-transforms" } # last tag: "turbopack-230922.3"
turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-230922.3" }

# General Deps

Expand Down
2 changes: 0 additions & 2 deletions packages/next-swc/crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ turbopack-binding = { workspace = true, features = [
"__swc_transform_modularize_imports",
"__swc_transform_relay",
] }
react_remove_properties = "0.3.0"
remove_console = "0.4.0"

[dev-dependencies]
turbopack-binding = { workspace = true, features = [
Expand Down
10 changes: 5 additions & 5 deletions packages/next-swc/crates/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,12 @@ pub mod next_ssg;
pub mod optimize_barrel;
pub mod optimize_server_react;
pub mod page_config;
pub mod react_remove_properties;
pub mod react_server_components;
pub mod remove_console;
pub mod server_actions;
pub mod shake_exports;
mod top_level_binding_collector;

#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -248,15 +251,12 @@ where
relay_plugin,
match &opts.remove_console {
Some(config) if config.truthy() =>
Either::Left(remove_console::remove_console(
config.clone(),
SyntaxContext::empty().apply_mark(unresolved_mark)
)),
Either::Left(remove_console::remove_console(config.clone())),
_ => Either::Right(noop()),
},
match &opts.react_remove_properties {
Some(config) if config.truthy() =>
Either::Left(react_remove_properties::react_remove_properties(config.clone())),
Either::Left(react_remove_properties::remove_properties(config.clone())),
_ => Either::Right(noop()),
},
match &opts.shake_exports {
Expand Down
72 changes: 72 additions & 0 deletions packages/next-swc/crates/core/src/react_remove_properties.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use regex::Regex;
use serde::Deserialize;
use turbopack_binding::swc::core::ecma::{
ast::*,
visit::{noop_fold_type, Fold, FoldWith},
};

#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum Config {
All(bool),
WithOptions(Options),
}

impl Config {
pub fn truthy(&self) -> bool {
match self {
Config::All(b) => *b,
Config::WithOptions(_) => true,
}
}
}

#[derive(Clone, Debug, Deserialize)]
pub struct Options {
#[serde(default)]
pub properties: Vec<String>,
}

struct RemoveProperties {
properties: Vec<Regex>,
}

impl RemoveProperties {
fn should_remove_property(&self, name: &str) -> bool {
self.properties.iter().any(|p| p.is_match(name))
}
}

impl Fold for RemoveProperties {
noop_fold_type!();

fn fold_jsx_opening_element(&mut self, mut el: JSXOpeningElement) -> JSXOpeningElement {
el.attrs.retain(|attr| {
!matches!(attr, JSXAttrOrSpread::JSXAttr(JSXAttr {
name: JSXAttrName::Ident(ident),
..
}) if self.should_remove_property(ident.sym.as_ref()))
});
el.fold_children_with(self)
}
}

pub fn remove_properties(config: Config) -> impl Fold {
let mut properties: Vec<Regex> = match config {
Config::WithOptions(x) => x
.properties
.iter()
.map(|pattern| {
Regex::new(pattern).unwrap_or_else(|e| {
panic!("error compiling property regex `{}`: {}", pattern, e);
})
})
.collect(),
_ => vec![],
};
if properties.is_empty() {
// Keep the default regex identical to `babel-plugin-react-remove-properties`.
properties.push(Regex::new(r"^data-test").unwrap());
}
RemoveProperties { properties }
}
131 changes: 131 additions & 0 deletions packages/next-swc/crates/core/src/remove_console.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
use serde::Deserialize;
use turbopack_binding::swc::core::{
common::{collections::AHashSet, DUMMY_SP},
ecma::{
ast::*,
atoms::JsWord,
visit::{noop_fold_type, Fold, FoldWith},
},
};

use crate::top_level_binding_collector::collect_top_level_decls;

#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
pub enum Config {
All(bool),
WithOptions(Options),
}

impl Config {
pub fn truthy(&self) -> bool {
match self {
Config::All(b) => *b,
Config::WithOptions(_) => true,
}
}
}

#[derive(Clone, Debug, Deserialize)]
pub struct Options {
#[serde(default)]
pub exclude: Vec<JsWord>,
}

struct RemoveConsole {
exclude: Vec<JsWord>,
bindings: Vec<AHashSet<Id>>,
}

impl RemoveConsole {
fn is_global_console(&self, ident: &Ident) -> bool {
&ident.sym == "console" && !self.bindings.iter().any(|x| x.contains(&ident.to_id()))
}

fn should_remove_call(&mut self, n: &CallExpr) -> bool {
let callee = &n.callee;
let member_expr = match callee {
Callee::Expr(e) => match &**e {
Expr::Member(m) => m,
_ => return false,
},
_ => return false,
};

// Don't attempt to evaluate computed properties.

if matches!(&member_expr.prop, MemberProp::Computed(..)) {
return false;
}

// Only proceed if the object is the global `console` object.
match &*member_expr.obj {
Expr::Ident(i) if self.is_global_console(i) => {}
_ => return false,
}

// Check if the property is requested to be excluded.
// Here we do an O(n) search on the list of excluded properties because the size
// should be small.
match &member_expr.prop {
MemberProp::Ident(i) if !self.exclude.iter().any(|x| *x == i.sym) => {}
_ => return false,
}

true
}
}

impl Fold for RemoveConsole {
noop_fold_type!();

fn fold_stmt(&mut self, stmt: Stmt) -> Stmt {
if let Stmt::Expr(e) = &stmt {
if let Expr::Call(c) = &*e.expr {
if self.should_remove_call(c) {
return Stmt::Empty(EmptyStmt { span: DUMMY_SP });
}
}
}
stmt.fold_children_with(self)
}

fn fold_function(&mut self, mut func: Function) -> Function {
let mut new_params: AHashSet<Id> = AHashSet::default();
for param in &func.params {
new_params.extend(collect_top_level_decls(param));
}

self.bindings.push(new_params);
self.bindings.push(collect_top_level_decls(&func));
func.body = func.body.fold_with(self);
self.bindings.pop().unwrap();
self.bindings.pop().unwrap();
func
}

fn fold_module(&mut self, module: Module) -> Module {
self.bindings.push(collect_top_level_decls(&module));
let m = module.fold_children_with(self);
self.bindings.pop().unwrap();
m
}

fn fold_script(&mut self, script: Script) -> Script {
self.bindings.push(collect_top_level_decls(&script));
let s = script.fold_with(self);
self.bindings.pop().unwrap();
s
}
}

pub fn remove_console(config: Config) -> impl Fold {
let exclude = match config {
Config::WithOptions(x) => x.exclude,
_ => vec![],
};
RemoveConsole {
exclude,
bindings: Default::default(),
}
}
131 changes: 131 additions & 0 deletions packages/next-swc/crates/core/src/top_level_binding_collector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
use std::hash::Hash;

use turbopack_binding::swc::core::{
common::{collections::AHashSet, SyntaxContext},
ecma::{
ast::{
ClassDecl, FnDecl, Ident, ImportDefaultSpecifier, ImportNamedSpecifier,
ImportStarAsSpecifier, ModuleItem, ObjectPatProp, Param, Pat, Stmt, VarDeclarator,
},
utils::ident::IdentLike,
visit::{noop_visit_type, Visit, VisitWith},
},
};

// Modified from swc_ecma_utils/src/lib.rs:BindingCollector.
pub struct TopLevelBindingCollector<I>
where
I: IdentLike + Eq + Hash + Send + Sync,
{
only: Option<SyntaxContext>,
bindings: AHashSet<I>,
is_pat_decl: bool,
}

impl<I> TopLevelBindingCollector<I>
where
I: IdentLike + Eq + Hash + Send + Sync,
{
fn add(&mut self, i: &Ident) {
if let Some(only) = self.only {
if only != i.span.ctxt {
return;
}
}

self.bindings.insert(I::from_ident(i));
}
}

impl<I> Visit for TopLevelBindingCollector<I>
where
I: IdentLike + Eq + Hash + Send + Sync,
{
noop_visit_type!();

fn visit_class_decl(&mut self, node: &ClassDecl) {
self.add(&node.ident);
}

fn visit_fn_decl(&mut self, node: &FnDecl) {
self.add(&node.ident);
}

fn visit_pat(&mut self, node: &Pat) {
if self.is_pat_decl {
match node {
Pat::Ident(i) => self.add(&i.id),
Pat::Object(o) => {
for prop in o.props.iter() {
match prop {
ObjectPatProp::Assign(a) => self.add(&a.key),
ObjectPatProp::KeyValue(k) => k.value.visit_with(self),
ObjectPatProp::Rest(_) => {}
}
}
}
Pat::Array(a) => {
for elem in a.elems.iter() {
elem.visit_with(self);
}
}
_ => {}
}
}
}

fn visit_param(&mut self, node: &Param) {
let old = self.is_pat_decl;
self.is_pat_decl = true;
node.visit_children_with(self);
self.is_pat_decl = old;
}

fn visit_import_default_specifier(&mut self, node: &ImportDefaultSpecifier) {
self.add(&node.local);
}

fn visit_import_named_specifier(&mut self, node: &ImportNamedSpecifier) {
self.add(&node.local);
}

fn visit_import_star_as_specifier(&mut self, node: &ImportStarAsSpecifier) {
self.add(&node.local);
}

fn visit_module_items(&mut self, nodes: &[ModuleItem]) {
for node in nodes {
node.visit_children_with(self)
}
}

fn visit_stmts(&mut self, nodes: &[Stmt]) {
for node in nodes {
node.visit_children_with(self)
}
}

fn visit_var_declarator(&mut self, node: &VarDeclarator) {
let old = self.is_pat_decl;
self.is_pat_decl = true;
node.name.visit_with(self);

self.is_pat_decl = false;
node.init.visit_with(self);
self.is_pat_decl = old;
}
}

pub fn collect_top_level_decls<I, N>(n: &N) -> AHashSet<I>
where
I: IdentLike + Eq + Hash + Send + Sync,
N: VisitWith<TopLevelBindingCollector<I>>,
{
let mut v = TopLevelBindingCollector {
only: None,
bindings: Default::default(),
is_pat_decl: false,
};
n.visit_with(&mut v);
v.bindings
}
Loading

0 comments on commit fefb27f

Please sign in to comment.