Skip to content

Commit

Permalink
feat(next-swc): Update swc (#39055)
Browse files Browse the repository at this point in the history
## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The examples guidelines are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples)
  • Loading branch information
kdy1 committed Jul 28, 2022
1 parent 377fddf commit 4eac75b
Show file tree
Hide file tree
Showing 51 changed files with 576 additions and 393 deletions.
374 changes: 130 additions & 244 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 @@ -26,18 +26,18 @@ swc_emotion = {path="../emotion"}
styled_components = {path="../styled_components"}
styled_jsx = {path="../styled_jsx"}
modularize_imports = {path="../modularize_imports"}
swc = "0.205.0"
swc_atoms = "0.2.13"
swc_common = { version = "0.23.0", features = ["concurrent", "sourcemap"] }
swc_ecma_loader = { version = "0.35.0", features = ["node", "lru"] }
swc_ecmascript = { version = "0.180.0", features = ["codegen", "minifier", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
swc_plugin_runner = { version = "0.64.0", optional = true, default-features = false }
swc_cached = "0.1.1"
swc = "0.212.1"
swc_atoms = "0.3.1"
swc_common = { version = "0.26.0", features = ["concurrent", "sourcemap", "plugin_transform_schema_v1"] }
swc_ecma_loader = { version = "0.38.0", features = ["node", "lru"] }
swc_ecmascript = { version = "0.186.0", features = ["codegen", "minifier", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
swc_plugin_runner = { version = "0.70.0", optional = true, default-features = false, features = ["plugin_transform_schema_v1"] }
swc_cached = "0.2.0"
tracing = { version = "0.1.32", features = ["release_max_level_info"] }
wasmer = { version = "2.3.0", optional = true, default-features = false }
wasmer-wasi = { version = "2.3.0", optional = true, default-features = false }

[dev-dependencies]
swc_ecma_transforms_testing = "0.99.0"
testing = "0.25.0"
swc_ecma_transforms_testing = "0.104.0"
testing = "0.28.0"
walkdir = "2.3.2"
13 changes: 7 additions & 6 deletions packages/next-swc/crates/emotion/Cargo.toml
Expand Up @@ -5,7 +5,7 @@ description = "AST Transforms for emotion"
license = "Apache-2.0"
name = "swc_emotion"
repository = "https://github.com/vercel/next.js.git"
version = "0.12.0"
version = "0.16.0"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand All @@ -18,12 +18,13 @@ radix_fmt = "1"
regex = "1.5"
serde = "1"
sourcemap = "6.0.1"
swc_atoms = "0.2.13"
swc_common = { version = "0.23.0", features = ["concurrent", "sourcemap"] }
swc_ecmascript = { version = "0.180.0", features = ["codegen", "utils", "visit"] }
swc_atoms = "0.3.1"
swc_common = { version = "0.26.0", features = ["concurrent", "sourcemap"] }
swc_ecmascript = { version = "0.186.0", features = ["codegen", "utils", "visit"] }
swc_trace_macro = "0.1.1"
tracing = { version = "0.1.32", features = ["release_max_level_info"] }

[dev-dependencies]
swc_ecma_transforms_testing = "0.99.0"
testing = "0.25.0"
swc_ecma_transforms_testing = "0.104.0"
testing = "0.28.0"
serde_json = "1"
81 changes: 81 additions & 0 deletions packages/next-swc/crates/emotion/src/import_map.rs
@@ -0,0 +1,81 @@
use serde::{Deserialize, Serialize};
use swc_atoms::JsWord;
use swc_common::collections::AHashMap;

use crate::{EmotionModuleConfig, ExportItem};

/// key: `importSource`
pub type ImportMap = AHashMap<JsWord, ImportMapValue>;

/// key: `localExportName`
pub type ImportMapValue = AHashMap<JsWord, Config>;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Config {
canonical_import: ImportItem,
}

/// `(packageName, exportName)`
#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct ImportItem(JsWord, JsWord);

pub(crate) fn expand_import_map(
map: Option<&ImportMap>,
mut imports: Vec<EmotionModuleConfig>,
) -> Vec<EmotionModuleConfig> {
if let Some(map) = map {
map.iter().for_each(|(import_source, value)| {
value
.iter()
.for_each(|(local_export_name, Config { canonical_import })| {
let ImportItem(package_name, export_name) = canonical_import;

if &*package_name == "@emotion/react" && &*export_name == "jsx" {
return;
}

let package_transformers = imports
.iter()
.find(|v| v.module_name == *package_name)
.unwrap_or_else(|| {
panic!(
"There is no transformer for the export '{}' in '{}'",
export_name, package_name
)
})
.clone();

let kind = package_transformers
.exported_names
.iter()
.find(|v| v.name == **export_name)
.map(|v| v.kind)
.or_else(|| {
if export_name == "default" {
package_transformers.default_export
} else {
None
}
})
.unwrap_or_else(|| {
panic!(
"failed to find export '{}' from package '{}'",
export_name, package_name
)
});

imports.push(EmotionModuleConfig {
module_name: import_source.clone(),
exported_names: vec![ExportItem {
name: local_export_name.to_string(),
kind,
}],
default_export: package_transformers.default_export,
});
})
});
}

imports
}
46 changes: 39 additions & 7 deletions packages/next-swc/crates/emotion/src/lib.rs
Expand Up @@ -3,17 +3,18 @@ use std::path::{Path, PathBuf};
use std::sync::Arc;

use fxhash::FxHashMap;
use import_map::ImportMap;
use once_cell::sync::Lazy;
use regex::Regex;
use serde::{Deserialize, Serialize};
use sourcemap::{RawToken, SourceMap as RawSourcemap};
use swc_atoms::JsWord;
use swc_common::comments::Comments;
use swc_common::util::take::Take;
use swc_common::{BytePos, SourceMap, DUMMY_SP};
use swc_common::{BytePos, SourceMapperDyn, DUMMY_SP};
use swc_ecmascript::ast::{
ArrayLit, CallExpr, JSXAttr, JSXAttrName, JSXAttrOrSpread, JSXAttrValue, JSXElementName,
JSXExpr, JSXExprContainer, JSXObject, SourceMapperExt,
JSXExpr, JSXExprContainer, JSXObject, ModuleExportName, SourceMapperExt,
};
use swc_ecmascript::utils::ExprFactory;
use swc_ecmascript::{
Expand All @@ -26,9 +27,18 @@ use swc_ecmascript::{
use swc_trace_macro::swc_trace;

mod hash;
mod import_map;

static EMOTION_OFFICIAL_LIBRARIES: Lazy<Vec<EmotionModuleConfig>> = Lazy::new(|| {
vec![
EmotionModuleConfig {
module_name: "@emotion/css".into(),
exported_names: vec![ExportItem {
name: "css".to_owned(),
kind: ExprKind::Css,
}],
default_export: Some(ExprKind::Css),
},
EmotionModuleConfig {
module_name: "@emotion/styled".into(),
exported_names: vec![],
Expand Down Expand Up @@ -81,6 +91,7 @@ pub struct EmotionOptions {
pub sourcemap: Option<bool>,
pub auto_label: Option<bool>,
pub label_format: Option<String>,
pub import_map: Option<ImportMap>,
}

impl Default for EmotionOptions {
Expand All @@ -90,6 +101,7 @@ impl Default for EmotionOptions {
sourcemap: Some(true),
auto_label: Some(true),
label_format: Some("[local]".to_owned()),
import_map: None,
}
}
}
Expand Down Expand Up @@ -142,7 +154,7 @@ enum PackageMeta {
pub fn emotion<C: Comments>(
emotion_options: EmotionOptions,
path: &Path,
cm: Arc<SourceMap>,
cm: Arc<SourceMapperDyn>,
comments: C,
) -> impl Fold {
EmotionTransformer::new(emotion_options, path, cm, comments)
Expand All @@ -154,18 +166,30 @@ pub struct EmotionTransformer<C: Comments> {
filepath: PathBuf,
dir: Option<String>,
filename: Option<String>,
cm: Arc<SourceMap>,
cm: Arc<SourceMapperDyn>,
comments: C,
import_packages: FxHashMap<Id, PackageMeta>,
emotion_target_class_name_count: usize,
current_context: Option<String>,
// skip `css` transformation if it in JSX Element/Attribute
in_jsx_element: bool,

registered_imports: Vec<EmotionModuleConfig>,
}

#[swc_trace]
impl<C: Comments> EmotionTransformer<C> {
pub fn new(options: EmotionOptions, path: &Path, cm: Arc<SourceMap>, comments: C) -> Self {
pub fn new(
options: EmotionOptions,
path: &Path,
cm: Arc<SourceMapperDyn>,
comments: C,
) -> Self {
let registered_imports = self::import_map::expand_import_map(
options.import_map.as_ref(),
EMOTION_OFFICIAL_LIBRARIES.to_vec(),
);

EmotionTransformer {
options,
filepath_hash: None,
Expand All @@ -181,6 +205,7 @@ impl<C: Comments> EmotionTransformer<C> {
emotion_target_class_name_count: 0,
current_context: None,
in_jsx_element: false,
registered_imports,
}
}

Expand Down Expand Up @@ -255,13 +280,20 @@ impl<C: Comments> EmotionTransformer<C> {
// import { css } from '@emotion/react'
// import * as emotionCss from '@emotion/react'
fn generate_import_info(&mut self, expr: &ImportDecl) {
for c in EMOTION_OFFICIAL_LIBRARIES.iter() {
for c in self.registered_imports.iter() {
if expr.src.value == c.module_name {
for specifier in expr.specifiers.iter() {
match specifier {
ImportSpecifier::Named(named) => {
for exported in c.exported_names.iter() {
if named.local.as_ref() == exported.name {
let matched = match &named.imported {
Some(imported) => match imported {
ModuleExportName::Ident(v) => v.sym == exported.name,
ModuleExportName::Str(v) => v.value == exported.name,
},
_ => named.local.as_ref() == exported.name,
};
if matched {
self.import_packages.insert(
named.local.to_id(),
PackageMeta::Named(exported.kind),
Expand Down
7 changes: 6 additions & 1 deletion packages/next-swc/crates/emotion/tests/fixture.rs
Expand Up @@ -16,7 +16,7 @@ fn ts_syntax() -> Syntax {
})
}

#[fixture("tests/fixture/*/input.tsx")]
#[fixture("tests/fixture/**/input.tsx")]
fn next_emotion_fixture(input: PathBuf) {
let output = input.parent().unwrap().join("output.ts");
test_fixture(
Expand All @@ -37,12 +37,17 @@ fn next_emotion_fixture(input: PathBuf) {
},
top_level_mark,
);

let test_import_map =
serde_json::from_str(include_str!("./testImportMap.json")).unwrap();

chain!(
swc_emotion::emotion(
EmotionOptions {
enabled: Some(true),
sourcemap: Some(true),
auto_label: Some(true),
import_map: Some(test_import_map),
..Default::default()
},
&PathBuf::from("input.ts"),
Expand Down
@@ -0,0 +1,8 @@
import * as React from 'react'
import { SomeGlobalFromCore } from 'package-two'

const getBgColor = () => ({ backgroundColor: '#fff' })

export default () => (
<SomeGlobalFromCore styles={{ color: 'hotpink', ...getBgColor() }} />
)
@@ -0,0 +1,15 @@
import { jsx as _jsx } from "react/jsx-runtime";
import * as React from 'react';
import { SomeGlobalFromCore } from 'package-two';
const getBgColor = ()=>({
backgroundColor: '#fff'
});
export default (()=>/*#__PURE__*/ _jsx(SomeGlobalFromCore, {
styles: [
{
color: 'hotpink',
...getBgColor()
},
"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgU29tZUdsb2JhbEZyb21Db3JlIH0gZnJvbSAncGFja2FnZS10d28nXG5cbmNvbnN0IGdldEJnQ29sb3IgPSAoKSA9PiAoeyBiYWNrZ3JvdW5kQ29sb3I6ICcjZmZmJyB9KVxuXG5leHBvcnQgZGVmYXVsdCAoKSA9PiAoXG4gIDxTb21lR2xvYmFsRnJvbUNvcmUgc3R5bGVzPXt7IGNvbG9yOiAnaG90cGluaycsIC4uLmdldEJnQ29sb3IoKSB9fSAvPlxuKVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQU1HIn0= */"
]
}));
@@ -0,0 +1,4 @@
import * as React from 'react'
import { SomeGlobalFromCore } from 'package-two'

export default () => <SomeGlobalFromCore styles={{ color: 'hotpink' }} />
@@ -0,0 +1,11 @@
import { jsx as _jsx } from "react/jsx-runtime";
import * as React from 'react';
import { SomeGlobalFromCore } from 'package-two';
export default (()=>/*#__PURE__*/ _jsx(SomeGlobalFromCore, {
styles: [
{
color: 'hotpink'
},
"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgU29tZUdsb2JhbEZyb21Db3JlIH0gZnJvbSAncGFja2FnZS10d28nXG5cbmV4cG9ydCBkZWZhdWx0ICgpID0+IDxTb21lR2xvYmFsRnJvbUNvcmUgc3R5bGVzPXt7IGNvbG9yOiAnaG90cGluaycgfX0gLz5cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHc0IifQ== */"
]
}));
@@ -0,0 +1,3 @@
import { nonDefaultStyled as someAlias } from 'package-one'

let SomeComp = someAlias.div({ color: 'hotpink' })
@@ -0,0 +1,7 @@
import { nonDefaultStyled as someAlias } from 'package-one';
let SomeComp = /*#__PURE__*/ someAlias("div", {
target: "ekie5mj0",
label: "SomeComp"
})({
color: 'hotpink'
}, "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG5vbkRlZmF1bHRTdHlsZWQgYXMgc29tZUFsaWFzIH0gZnJvbSAncGFja2FnZS1vbmUnXG5cbmxldCBTb21lQ29tcCA9IHNvbWVBbGlhcy5kaXYoeyBjb2xvcjogJ2hvdHBpbmsnIH0pXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRWUifQ== */");
@@ -0,0 +1,3 @@
import { nonDefaultStyled } from 'package-one'

let SomeComp = nonDefaultStyled.div({ color: 'hotpink' })
@@ -0,0 +1,7 @@
import { nonDefaultStyled } from 'package-one';
let SomeComp = /*#__PURE__*/ nonDefaultStyled("div", {
target: "ekie5mj0",
label: "SomeComp"
})({
color: 'hotpink'
}, "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG5vbkRlZmF1bHRTdHlsZWQgfSBmcm9tICdwYWNrYWdlLW9uZSdcblxubGV0IFNvbWVDb21wID0gbm9uRGVmYXVsdFN0eWxlZC5kaXYoeyBjb2xvcjogJ2hvdHBpbmsnIH0pXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRWUifQ== */");
@@ -0,0 +1,3 @@
import { nonDefaultStyled } from 'package-four'

let SomeComp = nonDefaultStyled.div({ color: 'hotpink' })
@@ -0,0 +1,7 @@
import { nonDefaultStyled } from 'package-four';
let SomeComp = /*#__PURE__*/ nonDefaultStyled("div", {
target: "ekie5mj0",
label: "SomeComp"
})({
color: 'hotpink'
}, "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IG5vbkRlZmF1bHRTdHlsZWQgfSBmcm9tICdwYWNrYWdlLWZvdXInXG5cbmxldCBTb21lQ29tcCA9IG5vbkRlZmF1bHRTdHlsZWQuZGl2KHsgY29sb3I6ICdob3RwaW5rJyB9KVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVlIn0= */");
@@ -0,0 +1,3 @@
import { something } from 'package-three'

something({ color: 'green' })
@@ -0,0 +1,4 @@
import { something } from 'package-three';
/*#__PURE__*/ something({
color: 'green'
}, "label:[local]", "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQudHMiLCJzb3VyY2VzIjpbImlucHV0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHNvbWV0aGluZyB9IGZyb20gJ3BhY2thZ2UtdGhyZWUnXG5cbnNvbWV0aGluZyh7IGNvbG9yOiAnZ3JlZW4nIH0pXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEifQ== */");

0 comments on commit 4eac75b

Please sign in to comment.