Skip to content

Commit

Permalink
fix(bundler): Fix statement ordering issue (#1264)
Browse files Browse the repository at this point in the history
swc_bundler:
 - Reduce binary size by reducing usage of visitor / folders.
 - Handle `export *` and `export { default }` from same source. (denoland/deno#8530, denoland/deno#8679)
 - Fix ordering of statements. (denoland/deno#8545)
 - Sort statements in wrapped modules. (denoland/deno#8211 (comment))
 - Exclude default export while handling `export *`.
 - Exclude `export { default }` and `export { foo as default }` while handling `export *`.
 - Make statements from same module to be injected together. (denoland/deno#8620)

swc_ecma_transforms:
 - fixer: Handle assignments in the callee of `new`  correctly.
 - fixer: Handle seqence expression in the callee of `new`  correctly.
  • Loading branch information
kdy1 authored Dec 27, 2020
1 parent 6941f29 commit b66ee58
Show file tree
Hide file tree
Showing 105 changed files with 3,078 additions and 2,135 deletions.
1 change: 1 addition & 0 deletions bundler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ swc_ecma_visit = {version = "0.22.0", path = "../ecmascript/visit"}

[dev-dependencies]
hex = "0.4"
ntest = "0.7.2"
reqwest = {version = "0.10.8", features = ["blocking"]}
sha-1 = "0.9"
swc_ecma_transforms = {version = "0.31.0", path = "../ecmascript/transforms", features = ["react"]}
Expand Down
3 changes: 3 additions & 0 deletions bundler/scripts/test.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/usr/bin/env bash
set -eux

cargo test --no-run

cargo test --lib
cargo test --test fixture
(cd ../spack && cargo test --test fixture)
cargo test --test deno $@ -- --nocapture
64 changes: 19 additions & 45 deletions bundler/src/bundler/chunk/circular.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
use super::plan::CircularPlan;
use crate::{
bundler::chunk::{merge::Ctx, sort::sort},
id::Id,
Bundler, Load, ModuleId, Resolve,
};
use crate::bundler::modules::Modules;
use crate::{bundler::chunk::merge::Ctx, id::Id, Bundler, Load, ModuleId, Resolve};
use anyhow::{Context, Error};
use swc_common::DUMMY_SP;
use swc_ecma_ast::*;
use swc_ecma_utils::find_ids;

#[cfg(test)]
mod tests;

/// Circular imports are hard to handle.
///
/// We use some dedicated method to handle circular dependencies.
Expand All @@ -25,7 +19,7 @@ where
ctx: &Ctx,
plan: &CircularPlan,
entry_id: ModuleId,
) -> Result<Module, Error> {
) -> Result<Modules, Error> {
assert!(
plan.chunks.len() >= 1,
"# of circular modules should be 2 or greater than 2 including entry. Got {:?}",
Expand All @@ -34,11 +28,7 @@ where

if !ctx.merged.insert(entry_id) {
log::debug!("[circular] skip: {:?}", entry_id);
return Ok(Module {
span: DUMMY_SP,
body: Default::default(),
shebang: Default::default(),
});
return Ok(Modules::empty(self.injected_ctxt));
}

log::debug!("[circular] Stsrting with: {:?}", entry_id);
Expand All @@ -50,7 +40,7 @@ where
.context("failed to merge dependency of a cyclic module")?;

let mut exports = vec![];
for item in entry.body.iter_mut() {
for item in entry.iter_mut() {
match item {
ModuleItem::ModuleDecl(decl) => match decl {
ModuleDecl::ExportDecl(export) => match &export.decl {
Expand Down Expand Up @@ -125,16 +115,14 @@ where
entry = new_module;

if !exports.is_empty() {
entry
.body
.push(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(
NamedExport {
span: DUMMY_SP.with_ctxt(self.synthesized_ctxt),
specifiers: exports,
src: None,
type_only: false,
},
)));
entry.inject(ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(
NamedExport {
span: DUMMY_SP.with_ctxt(self.synthesized_ctxt),
specifiers: exports,
src: None,
type_only: false,
},
)));
}

// print_hygiene("[circular] done", &self.cm, &entry);
Expand All @@ -146,10 +134,10 @@ where
pub(super) fn merge_circular_modules(
&self,
ctx: &Ctx,
mut entry: Module,
mut entry: Modules,
entry_id: ModuleId,
mut deps: Vec<ModuleId>,
) -> Result<Module, Error> {
) -> Result<Modules, Error> {
deps.retain(|&dep| {
if dep == entry_id {
return false;
Expand All @@ -167,40 +155,26 @@ where
deps.sort();

self.run(|| {
let mut dep_body = vec![];

for dep in deps {
let dep_info = self.scope.get_module(dep).unwrap();
let mut dep = self
.merge_modules(ctx, dep, false, false)
.context("failed to merge dependency of a cyclic module")?;

// print_hygiene("[circular] dep:init 1", &self.cm, &dep);
// print_hygiene("[circular] dep:init 1", &self.cm, &dep.clone().into());

self.handle_import_deps(ctx, &dep_info, &mut dep, true);

// print_hygiene("[circular] dep:init 2", &self.cm, &dep);

dep_body.extend(dep.body);
entry.prepend_all(dep);
}

// dep = dep.fold_with(&mut Unexporter);
// print_hygiene("before circular sort", &self.cm, &entry.clone().into());

// Merge code
entry.body = merge_respecting_order(dep_body, entry.body);
// entry.sort();

Ok(entry)
})
}
}

fn merge_respecting_order(dep: Vec<ModuleItem>, entry: Vec<ModuleItem>) -> Vec<ModuleItem> {
let mut new = Vec::with_capacity(dep.len() + entry.len());

new.extend(entry);
new.extend(dep);

sort(&mut new);

new
}
110 changes: 0 additions & 110 deletions bundler/src/bundler/chunk/circular/tests.rs

This file was deleted.

52 changes: 21 additions & 31 deletions bundler/src/bundler/chunk/cjs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::merge::Unexporter;
use crate::bundler::modules::Modules;
use crate::{
bundler::{
chunk::{merge::Ctx, plan::Dependancy},
Expand All @@ -7,12 +8,12 @@ use crate::{
Bundler, Load, Resolve,
};
use anyhow::Error;
use std::{borrow::Cow, sync::atomic::Ordering};
use std::sync::atomic::Ordering;
use swc_atoms::js_word;
use swc_common::{SyntaxContext, DUMMY_SP};
use swc_ecma_ast::{ModuleItem, *};
use swc_ecma_utils::{prepend, quote_ident, undefined, ExprFactory};
use swc_ecma_visit::{noop_visit_mut_type, FoldWith, VisitMut, VisitMutWith};
use swc_ecma_utils::{quote_ident, undefined, ExprFactory};
use swc_ecma_visit::{noop_visit_mut_type, VisitMut, VisitMutWith};

impl<L, R> Bundler<'_, L, R>
where
Expand Down Expand Up @@ -44,9 +45,9 @@ where
&self,
ctx: &Ctx,
is_entry: bool,
entry: &mut Module,
entry: &mut Modules,
info: &TransformedModule,
dep: Cow<Module>,
dep: Modules,
dep_info: &TransformedModule,
targets: &mut Vec<Dependancy>,
) -> Result<(), Error> {
Expand All @@ -62,7 +63,7 @@ where
load_var: Ident::new("load".into(), DUMMY_SP.with_ctxt(dep_info.export_ctxt())),
replaced: false,
};
entry.body.visit_mut_with(&mut v);
entry.visit_mut_with(&mut v);

if v.replaced {
if let Some(idx) = targets.iter().position(|v| v.id == dep_info.id) {
Expand All @@ -74,21 +75,18 @@ where
{
info.helpers.require.store(true, Ordering::SeqCst);

let mut dep = dep.into_owned().fold_with(&mut Unexporter);
dep.visit_mut_with(&mut ImportDropper);
let mut dep = dep.fold_with(&mut Unexporter);
drop_module_decls(&mut dep);
dep.visit_mut_with(&mut DefaultHandler {
local_ctxt: dep_info.local_ctxt(),
});

prepend(
&mut entry.body,
ModuleItem::Stmt(wrap_module(
SyntaxContext::empty(),
dep_info.local_ctxt(),
load_var,
dep,
)),
);
entry.prepend(ModuleItem::Stmt(wrap_module(
SyntaxContext::empty(),
dep_info.local_ctxt(),
load_var,
dep.into(),
)));

log::warn!("Injecting load");
}
Expand All @@ -105,7 +103,7 @@ where
false,
entry,
info,
Cow::Borrowed(&dep_info.module),
Modules::from((*dep_info.module).clone(), self.injected_ctxt),
&dep_info,
targets,
)?;
Expand Down Expand Up @@ -338,19 +336,11 @@ impl VisitMut for RequireReplacer {
}
}

struct ImportDropper;

impl VisitMut for ImportDropper {
noop_visit_mut_type!();

fn visit_mut_module_item(&mut self, i: &mut ModuleItem) {
match i {
ModuleItem::ModuleDecl(..) => {
*i = ModuleItem::Stmt(Stmt::Empty(EmptyStmt { span: DUMMY_SP }))
}
ModuleItem::Stmt(_) => {}
}
}
fn drop_module_decls(modules: &mut Modules) {
modules.retain_mut(|i| match i {
ModuleItem::ModuleDecl(..) => false,
ModuleItem::Stmt(_) => true,
})
}

struct DefaultHandler {
Expand Down
Loading

0 comments on commit b66ee58

Please sign in to comment.