diff --git a/bundler/Cargo.toml b/bundler/Cargo.toml index 5d76676785f6..5614e9d88ed0 100644 --- a/bundler/Cargo.toml +++ b/bundler/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" license = "Apache-2.0/MIT" name = "swc_bundler" repository = "https://github.com/swc-project/swc.git" -version = "0.17.2" +version = "0.17.3" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] diff --git a/bundler/src/bundler/chunk/merge.rs b/bundler/src/bundler/chunk/merge.rs index cb98a4776301..b01507d48780 100644 --- a/bundler/src/bundler/chunk/merge.rs +++ b/bundler/src/bundler/chunk/merge.rs @@ -18,7 +18,7 @@ use std::{borrow::Cow, collections::HashMap, mem::take}; use swc_atoms::js_word; use swc_common::{sync::Lock, FileName, SyntaxContext, DUMMY_SP}; use swc_ecma_ast::*; -use swc_ecma_utils::{find_ids, prepend, private_ident}; +use swc_ecma_utils::{find_ids, prepend, private_ident, ExprFactory}; use swc_ecma_visit::{noop_fold_type, noop_visit_mut_type, Fold, FoldWith, VisitMut, VisitMutWith}; use util::CHashSet; @@ -102,6 +102,7 @@ where &self, ctx: &Ctx, dep_id: ModuleId, + src: &Source, specifiers: &[Specifier], ) -> Result { log::debug!("Merging {:?} directly", dep_id); @@ -114,27 +115,25 @@ where let mut module = self.get_module_for_merging(ctx, dep_id, false)?; module = self.wrap_esm(ctx, dep_id, module)?; - { - // Inject local_name = wrapped_esm_module_name + // Inject local_name = wrapped_esm_module_name + let module_ident = specifiers + .iter() + .find_map(|specifier| match specifier { + Specifier::Namespace { + local, all: true, .. + } => Some(local.clone()), + _ => None, + }) + .unwrap(); - let module_ident = specifiers - .iter() - .find_map(|specifier| match specifier { - Specifier::Namespace { - local, all: true, .. - } => Some(local.clone()), - _ => None, - }) - .unwrap(); - - module.body.push( - self.scope - .wrapped_esm_id(dep_id) - .unwrap() - .assign_to(module_ident) - .into_module_item("merge_direct_import"), - ); - } + let esm_id = self.scope.wrapped_esm_id(dep_id).unwrap(); + + module.body.push( + esm_id + .clone() + .assign_to(module_ident.clone()) + .into_module_item("merge_direct_import"), + ); let plan = ctx.plan.normal.get(&dep_id); let default_plan; @@ -158,6 +157,23 @@ where .merge_deps(ctx, false, module, plan, &dep_info, false) .context("failed to merge dependencies")?; + // Required to handle edge cases liek https://github.com/denoland/deno/issues/8530 + for specifier in specifiers { + match specifier { + Specifier::Specific { local, alias } => { + let i = alias.clone().unwrap_or_else(|| local.clone()); + + let from = esm_id.clone().into_ident().make_member(i.clone()); + + module.body.push( + from.assign_to(i.with_ctxt(src.export_ctxt)) + .into_module_item("namespace_with_normal"), + ); + } + Specifier::Namespace { .. } => continue, + } + } + self.handle_import_deps(ctx, &dep_info, &mut module, false); module @@ -336,8 +352,8 @@ where .iter() .find(|(src, _)| src.module_id == dep.id); - if let Some((_, specifiers)) = res { - self.merge_direct_import(ctx, dep.id, &specifiers)? + if let Some((src, specifiers)) = res { + self.merge_direct_import(ctx, dep.id, &src, &specifiers)? } else { // Common js requires different planning strategy. self.merge_transitive_import(ctx, dep.id)? diff --git a/bundler/src/bundler/import/mod.rs b/bundler/src/bundler/import/mod.rs index 87ee35439a96..f7c04723e15a 100644 --- a/bundler/src/bundler/import/mod.rs +++ b/bundler/src/bundler/import/mod.rs @@ -122,6 +122,19 @@ where idents_to_deglob: HashSet, } +impl RawImports { + fn insert(&mut self, import: &ImportDecl) { + for prev in self.imports.iter_mut() { + if prev.src.value == import.src.value { + prev.specifiers.extend(import.specifiers.clone()); + return; + } + } + + self.imports.push(import.clone()); + } +} + impl ImportHandler<'_, '_, L, R> where L: Load, @@ -217,7 +230,7 @@ where } } - self.info.imports.push(import.clone()); + self.info.insert(&import); return import; } @@ -306,17 +319,6 @@ where if use_ns { wrapping_required.push(import.src.value.clone()); - - import.specifiers.retain(|s| match s { - ImportSpecifier::Namespace(_) => true, - _ => false, - }); - - debug_assert_ne!( - import.specifiers, - vec![], - "forced_ns should be modified only if a namespace import specifier exist" - ); } else { // De-glob namespace imports import.specifiers.retain(|s| match s { @@ -506,7 +508,7 @@ where }; if self.top_level { - self.info.imports.push(decl); + self.info.insert(&decl); return Expr::Call(e); } diff --git a/bundler/tests/deno.rs b/bundler/tests/deno.rs index 535635d54892..eec725ab6976 100644 --- a/bundler/tests/deno.rs +++ b/bundler/tests/deno.rs @@ -368,6 +368,17 @@ fn deno_8481_1() { ) } +#[test] +fn deno_8530() { + run("tests/deno/deno-8530/input/entry.ts", &[]) +} + +#[test] +#[ignore] +fn deno_8545() { + run("tests/deno/deno-8545/input/entry.ts", &[]) +} + #[test] fn merging_order_01() { run( diff --git a/bundler/tests/deno/deno-8530/input/entry.ts b/bundler/tests/deno/deno-8530/input/entry.ts new file mode 100644 index 000000000000..03eebd7e0aa6 --- /dev/null +++ b/bundler/tests/deno/deno-8530/input/entry.ts @@ -0,0 +1,9 @@ +import Head from "https://deno.land/x/aleph/head.ts" +import * as Head2 from "https://deno.land/x/aleph/head.ts" +console.log(Head, Head2); +if (typeof Head !== 'function') { + throw new Error() +} +if (typeof Head2 !== 'object') { + throw new Error() +} \ No newline at end of file diff --git a/bundler/tests/deno/deno-8545/input/entry.ts b/bundler/tests/deno/deno-8545/input/entry.ts new file mode 100644 index 000000000000..665d93d971f8 --- /dev/null +++ b/bundler/tests/deno/deno-8545/input/entry.ts @@ -0,0 +1,18 @@ +import { Application, Router } from "https://raw.githubusercontent.com/kdy1/oak-bundle-issue/master/deps.ts"; + +const app = new Application(); +const router = new Router(); + +router.get("/", (ctx) => { + ctx.response.body = "Index Page"; +}); + +router.get("/users", (ctx) => { + ctx.response.body = "Users Page"; +}); + +app.use(router.routes()); +app.use(router.allowedMethods()); + +console.log(`Now listening on http://0.0.0.0:3000`); +await app.listen("0.0.0.0:3000"); \ No newline at end of file diff --git a/ecmascript/codegen/Cargo.toml b/ecmascript/codegen/Cargo.toml index 529451a62562..cdd5d3a2b7b6 100644 --- a/ecmascript/codegen/Cargo.toml +++ b/ecmascript/codegen/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = "Apache-2.0/MIT" name = "swc_ecma_codegen" repository = "https://github.com/swc-project/swc.git" -version = "0.41.1" +version = "0.41.2" [dependencies] bitflags = "1" diff --git a/ecmascript/codegen/src/lib.rs b/ecmascript/codegen/src/lib.rs index d3bfb9f929af..724e644d4bf1 100644 --- a/ecmascript/codegen/src/lib.rs +++ b/ecmascript/codegen/src/lib.rs @@ -2463,8 +2463,11 @@ fn escape<'s>(cm: &SourceMap, span: Span, s: &'s str, single_quote: Option } 'u' => match orig_iter.next() { Some('{') => { + buf.push('{'); loop { - if orig_iter.next() == Some('}') { + let ch = orig_iter.next(); + buf.extend(ch); + if ch == Some('}') { break; } } diff --git a/ecmascript/codegen/src/tests.rs b/ecmascript/codegen/src/tests.rs index fd3bf76d977a..b1a311c7ca0e 100644 --- a/ecmascript/codegen/src/tests.rs +++ b/ecmascript/codegen/src/tests.rs @@ -470,6 +470,22 @@ fn integration_01_reduced_01() { ); } +#[test] +fn dneo_8541_1() { + test_from_to( + "React.createElement('span', null, '\\u{b7}');", + "React.createElement('span', null, '\\u{b7}');", + ); +} + +#[test] +fn dneo_8541_2() { + test_from_to( + "React.createElement('span', null, '\\u00b7');", + "React.createElement('span', null, '\\u00b7');", + ); +} + #[derive(Debug, Clone)] struct Buf(Arc>>); impl Write for Buf { diff --git a/ecmascript/codegen/tests/references/20aca21e32bf7772.js b/ecmascript/codegen/tests/references/20aca21e32bf7772.js index 001e16d6cf78..b9c8d7090663 100644 --- a/ecmascript/codegen/tests/references/20aca21e32bf7772.js +++ b/ecmascript/codegen/tests/references/20aca21e32bf7772.js @@ -1 +1 @@ -('\u'); +('\u{10FFFF}'); diff --git a/ecmascript/codegen/tests/references/37c0f5275362d1c9.js b/ecmascript/codegen/tests/references/37c0f5275362d1c9.js index 8f04b77029d2..1e13f660375a 100644 --- a/ecmascript/codegen/tests/references/37c0f5275362d1c9.js +++ b/ecmascript/codegen/tests/references/37c0f5275362d1c9.js @@ -1 +1 @@ -"\u"; +"\u{00000000034}"; diff --git a/ecmascript/codegen/tests/references/4a0d9236bc523b77.js b/ecmascript/codegen/tests/references/4a0d9236bc523b77.js index 001e16d6cf78..bc8b9e6baeb8 100644 --- a/ecmascript/codegen/tests/references/4a0d9236bc523b77.js +++ b/ecmascript/codegen/tests/references/4a0d9236bc523b77.js @@ -1 +1 @@ -('\u'); +('\u{0000000000F8}'); diff --git a/ecmascript/codegen/tests/references/78e1b8a4f3318967.js b/ecmascript/codegen/tests/references/78e1b8a4f3318967.js index 63a693d9c0dc..9506b9f592dc 100644 --- a/ecmascript/codegen/tests/references/78e1b8a4f3318967.js +++ b/ecmascript/codegen/tests/references/78e1b8a4f3318967.js @@ -1 +1 @@ -"\u\u"; +"\u{714E}\u{8336}"; diff --git a/ecmascript/codegen/tests/references/cf0eb6e6c4317c33.js b/ecmascript/codegen/tests/references/cf0eb6e6c4317c33.js index 001e16d6cf78..8971558234ea 100644 --- a/ecmascript/codegen/tests/references/cf0eb6e6c4317c33.js +++ b/ecmascript/codegen/tests/references/cf0eb6e6c4317c33.js @@ -1 +1 @@ -('\u'); +('\u{00F8}'); diff --git a/ecmascript/codegen/tests/references/d81d71f4121e3193.js b/ecmascript/codegen/tests/references/d81d71f4121e3193.js index 001e16d6cf78..6344f2ee0204 100644 --- a/ecmascript/codegen/tests/references/d81d71f4121e3193.js +++ b/ecmascript/codegen/tests/references/d81d71f4121e3193.js @@ -1 +1 @@ -('\u'); +('\u{0}'); diff --git a/ecmascript/codegen/tests/references/e9682c37a1a959e1.js b/ecmascript/codegen/tests/references/e9682c37a1a959e1.js index ee2e4966bf01..48090185ee56 100644 --- a/ecmascript/codegen/tests/references/e9682c37a1a959e1.js +++ b/ecmascript/codegen/tests/references/e9682c37a1a959e1.js @@ -1 +1 @@ -"\u\u\u"; +"\u{20BB7}\u{91CE}\u{5BB6}";