mirror of
https://github.com/swc-project/swc.git
synced 2024-11-24 02:06:08 +03:00
bundler: fix bugs (#1105)
swc_bundler: - Correct lca for circular dependencies. - Handle namespaced imports. (#1109) - Handle namespaced reexports. (#1110) - Handle shorthand properly. (#1111) - Implement `import.meta` (#1115) - Handle reexport mixed with imports correctly. (#1116) - Handle export default decls in computed-key modules. - Remove all export * from. output. (#1118) - Handle export of class or function declaration in a computed module properly. (#1119) swc_ecma_transforms: - Do not rename class members. (#1117)
This commit is contained in:
parent
1f00d9ba26
commit
9879fa59c8
2
.github/workflows/cargo.yml
vendored
2
.github/workflows/cargo.yml
vendored
@ -14,6 +14,8 @@ on: [push, pull_request]
|
||||
|
||||
env:
|
||||
CARGO_INCREMENTAL: 0
|
||||
# To make spack tests reliable
|
||||
RAYON_NUM_THREADS: 1
|
||||
CI: "1"
|
||||
|
||||
jobs:
|
||||
|
@ -7,7 +7,7 @@ edition = "2018"
|
||||
license = "Apache-2.0/MIT"
|
||||
name = "swc_atoms"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
|
||||
[dependencies]
|
||||
string_cache = "0.8"
|
||||
|
@ -626,6 +626,7 @@ key
|
||||
keyof
|
||||
length
|
||||
let
|
||||
main
|
||||
meta
|
||||
module
|
||||
namespace
|
||||
@ -660,6 +661,7 @@ typeof
|
||||
undefined
|
||||
unique
|
||||
unknown
|
||||
url
|
||||
var
|
||||
void
|
||||
while
|
||||
|
@ -6,7 +6,7 @@ edition = "2018"
|
||||
license = "Apache-2.0/MIT"
|
||||
name = "swc_bundler"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
version = "0.8.0"
|
||||
version = "0.9.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
[features]
|
||||
@ -25,7 +25,7 @@ radix_fmt = "1"
|
||||
rayon = {version = "1", optional = true}
|
||||
relative-path = "1.2"
|
||||
retain_mut = "=0.1.1"
|
||||
swc_atoms = {version = "0.2", path = "../atoms"}
|
||||
swc_atoms = {version = "0.2.4", path = "../atoms"}
|
||||
swc_common = {version = "0.10.0", path = "../common"}
|
||||
swc_ecma_ast = {version = "0.32.0", path = "../ecmascript/ast"}
|
||||
swc_ecma_codegen = {version = "0.36.0", path = "../ecmascript/codegen"}
|
||||
@ -35,4 +35,6 @@ swc_ecma_utils = {version = "0.22.0", path = "../ecmascript/utils"}
|
||||
swc_ecma_visit = {version = "0.18.0", path = "../ecmascript/visit"}
|
||||
|
||||
[dev-dependencies]
|
||||
reqwest = {version = "0.10.8", features = ["blocking"]}
|
||||
testing = {version = "0.10.0", path = "../testing"}
|
||||
url = "2.1.1"
|
||||
|
@ -1,7 +1,8 @@
|
||||
use anyhow::Error;
|
||||
use std::{collections::HashMap, io::stdout};
|
||||
use swc_bundler::{BundleKind, Bundler, Config, Load, Resolve};
|
||||
use swc_common::{sync::Lrc, FileName, FilePathMapping, Globals, SourceMap};
|
||||
use swc_bundler::{BundleKind, Bundler, Config, Hook, Load, Resolve};
|
||||
use swc_common::{sync::Lrc, FileName, FilePathMapping, Globals, SourceMap, Span};
|
||||
use swc_ecma_ast::Expr;
|
||||
use swc_ecma_codegen::{text_writer::JsWriter, Emitter};
|
||||
use swc_ecma_parser::{lexer::Lexer, EsConfig, Parser, StringInput, Syntax};
|
||||
|
||||
@ -22,6 +23,7 @@ fn main() {
|
||||
external_modules,
|
||||
..Default::default()
|
||||
},
|
||||
Box::new(Noop),
|
||||
);
|
||||
let mut entries = HashMap::default();
|
||||
entries.insert("main".to_string(), FileName::Real("assets/main.js".into()));
|
||||
@ -104,3 +106,11 @@ impl Resolve for PathResolver {
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
struct Noop;
|
||||
|
||||
impl Hook for Noop {
|
||||
fn get_import_meta_url(&self, _: Span, _: &FileName) -> Result<Option<Expr>, Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,11 @@ where
|
||||
{
|
||||
let mut normal_reexports = vec![];
|
||||
let mut star_reexports = vec![];
|
||||
for (src, mut specifiers) in additional_modules {
|
||||
for (src, specifiers) in additional_modules {
|
||||
if specifiers.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If a dependency is indirect, we need to export items from it manually.
|
||||
let is_indirect = !nomral_plan.chunks.contains(&src.module_id);
|
||||
|
||||
@ -139,12 +143,6 @@ where
|
||||
} else {
|
||||
&mut normal_reexports
|
||||
};
|
||||
if specifiers.is_empty() {
|
||||
//
|
||||
let dep = self.scope.get_module(src.module_id).unwrap();
|
||||
|
||||
specifiers = dep.exports.items.clone();
|
||||
}
|
||||
|
||||
for specifier in specifiers {
|
||||
let (imported, exported) = match specifier {
|
||||
@ -235,7 +233,11 @@ where
|
||||
entry.body.visit_mut_with(&mut injector);
|
||||
|
||||
// print_hygiene(
|
||||
// &format!("entry:injection {:?} <- {:?}", info.ctxt(), src.ctxt,),
|
||||
// &format!(
|
||||
// "entry:reexport injection {:?} <- {:?}",
|
||||
// info.ctxt(),
|
||||
// src.ctxt,
|
||||
// ),
|
||||
// &self.cm,
|
||||
// &entry,
|
||||
// );
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
load::Load,
|
||||
resolve::Resolve,
|
||||
util::{self, IntoParallelIterator},
|
||||
Bundler,
|
||||
Bundler, Hook,
|
||||
};
|
||||
use anyhow::{Context, Error};
|
||||
#[cfg(feature = "concurrent")]
|
||||
@ -13,7 +13,7 @@ use rayon::iter::ParallelIterator;
|
||||
use retain_mut::RetainMut;
|
||||
use std::{borrow::Cow, mem::take};
|
||||
use swc_atoms::js_word;
|
||||
use swc_common::{SyntaxContext, DUMMY_SP};
|
||||
use swc_common::{FileName, SyntaxContext, DUMMY_SP};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_utils::prepend_stmts;
|
||||
use swc_ecma_visit::{noop_fold_type, noop_visit_mut_type, Fold, FoldWith, VisitMut, VisitMutWith};
|
||||
@ -61,6 +61,12 @@ where
|
||||
};
|
||||
|
||||
let mut entry: Module = (*info.module).clone();
|
||||
entry.visit_mut_with(&mut ImportMetaHandler {
|
||||
file: &info.fm.name,
|
||||
hook: &self.hook,
|
||||
is_entry,
|
||||
err: None,
|
||||
});
|
||||
|
||||
// print_hygiene(&format!("{}", info.fm.name), &self.cm, &entry);
|
||||
|
||||
@ -274,7 +280,11 @@ where
|
||||
// print_hygiene("entry:after:injection", &self.cm, &entry);
|
||||
|
||||
log::debug!("Merged {} as an es module", info.fm.name);
|
||||
// print_hygiene("ES6", &self.cm, &entry);
|
||||
// print_hygiene(
|
||||
// &format!("ES6: {:?} <- {:?}", info.ctxt(), dep_info.ctxt()),
|
||||
// &self.cm,
|
||||
// &entry,
|
||||
// );
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -538,3 +548,84 @@ impl VisitMut for DefaultRenamer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ImportMetaHandler<'a, 'b> {
|
||||
file: &'a FileName,
|
||||
hook: &'a Box<dyn 'b + Hook>,
|
||||
is_entry: bool,
|
||||
err: Option<Error>,
|
||||
}
|
||||
|
||||
impl VisitMut for ImportMetaHandler<'_, '_> {
|
||||
fn visit_mut_member_expr(&mut self, e: &mut MemberExpr) {
|
||||
if self.err.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
if e.computed {
|
||||
e.obj.visit_mut_with(self);
|
||||
}
|
||||
|
||||
e.prop.visit_mut_with(self);
|
||||
}
|
||||
|
||||
fn visit_mut_expr(&mut self, e: &mut Expr) {
|
||||
e.visit_mut_children_with(self);
|
||||
|
||||
match e {
|
||||
Expr::Member(me) => {
|
||||
if !me.computed {
|
||||
match &me.obj {
|
||||
ExprOrSuper::Super(_) => {}
|
||||
ExprOrSuper::Expr(obj) => match &**obj {
|
||||
Expr::MetaProp(MetaPropExpr {
|
||||
meta:
|
||||
Ident {
|
||||
sym: js_word!("import"),
|
||||
..
|
||||
},
|
||||
prop:
|
||||
Ident {
|
||||
sym: js_word!("meta"),
|
||||
..
|
||||
},
|
||||
..
|
||||
}) => match &*me.prop {
|
||||
Expr::Ident(Ident {
|
||||
sym: js_word!("url"),
|
||||
..
|
||||
}) => {
|
||||
let res = self.hook.get_import_meta_url(me.span, self.file);
|
||||
match res {
|
||||
Ok(v) => match v {
|
||||
Some(expr) => {
|
||||
*e = expr;
|
||||
return;
|
||||
}
|
||||
None => {}
|
||||
},
|
||||
Err(err) => self.err = Some(err),
|
||||
}
|
||||
}
|
||||
Expr::Ident(Ident {
|
||||
sym: js_word!("main"),
|
||||
..
|
||||
}) if !self.is_entry => {
|
||||
*e = Expr::Lit(Lit::Bool(Bool {
|
||||
span: me.span,
|
||||
value: false,
|
||||
}));
|
||||
return;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
|
||||
_ => {}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,12 +48,22 @@ pub(super) fn least_common_ancestor(g: &ModuleGraph, module_ids: &[ModuleId]) ->
|
||||
});
|
||||
}
|
||||
|
||||
fn check_itself<I>(li: I, ri: &[ModuleId]) -> Option<ModuleId>
|
||||
fn check_itself<I>(g: &ModuleGraph, li: I, ri: &[ModuleId]) -> Option<ModuleId>
|
||||
where
|
||||
I: IntoIterator<Item = ModuleId>,
|
||||
{
|
||||
for l in li {
|
||||
// Root
|
||||
if g.neighbors_directed(l, Incoming).count() == 0 {
|
||||
return Some(l);
|
||||
}
|
||||
|
||||
for &r in ri {
|
||||
// Root
|
||||
if g.neighbors_directed(r, Incoming).count() == 0 {
|
||||
return Some(l);
|
||||
}
|
||||
|
||||
if l == r {
|
||||
return Some(l);
|
||||
}
|
||||
@ -64,32 +74,40 @@ where
|
||||
}
|
||||
|
||||
fn check_itself_and_parent(g: &ModuleGraph, li: &[ModuleId], ri: &[ModuleId]) -> Option<ModuleId> {
|
||||
if let Some(id) = check_itself(li.iter().copied(), ri) {
|
||||
if let Some(id) = check_itself(g, li.iter().copied(), ri) {
|
||||
return Some(id);
|
||||
}
|
||||
|
||||
for &l in li {
|
||||
if let Some(id) = check_itself(g.neighbors_directed(l, Incoming), ri) {
|
||||
if let Some(id) = check_itself_and_parent(
|
||||
g,
|
||||
&g.neighbors_directed(l, Incoming).collect::<Vec<_>>(),
|
||||
ri,
|
||||
) {
|
||||
return Some(id);
|
||||
}
|
||||
}
|
||||
|
||||
for &r in ri {
|
||||
if let Some(id) = check_itself(g.neighbors_directed(r, Incoming), li) {
|
||||
if let Some(id) = check_itself_and_parent(
|
||||
g,
|
||||
&g.neighbors_directed(r, Incoming).collect::<Vec<_>>(),
|
||||
li,
|
||||
) {
|
||||
return Some(id);
|
||||
}
|
||||
}
|
||||
|
||||
for &l in li {
|
||||
for &r in ri {
|
||||
let lv = g.neighbors_directed(l, Incoming).collect::<Vec<_>>();
|
||||
let rv = g.neighbors_directed(r, Incoming).collect::<Vec<_>>();
|
||||
// for &l in li {
|
||||
// for &r in ri {
|
||||
// let lv = g.neighbors_directed(l, Incoming).collect::<Vec<_>>();
|
||||
// let rv = g.neighbors_directed(r, Incoming).collect::<Vec<_>>();
|
||||
|
||||
if let Some(id) = check_itself_and_parent(g, &lv, &rv) {
|
||||
return Some(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if let Some(id) = check_itself_and_parent(g, &lv, &rv) {
|
||||
// return Some(id);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
None
|
||||
}
|
||||
|
@ -446,7 +446,9 @@ where
|
||||
.map(|v| &v.0)
|
||||
.chain(m.exports.reexports.iter().map(|v| &v.0))
|
||||
{
|
||||
log::debug!("Dependency: {:?} => {:?}", module_id, src.module_id);
|
||||
if !builder.direct_deps.contains_edge(module_id, src.module_id) {
|
||||
log::debug!("Dependency: {:?} => {:?}", module_id, src.module_id);
|
||||
}
|
||||
|
||||
builder.direct_deps.add_edge(module_id, src.module_id, 0);
|
||||
|
||||
|
@ -543,8 +543,8 @@ fn cjs_004() {
|
||||
assert_eq!(p.circular.len(), 0);
|
||||
// As both of a and b depend on `common`, it should be merged into a parent
|
||||
// module.
|
||||
assert_normal(t, &p, "main", &["entry"]);
|
||||
assert_normal_transitive(t, &p, "entry", &["a", "b"], &["common"]);
|
||||
assert_normal_transitive(t, &p, "main", &["entry"], &["common"]);
|
||||
assert_normal_transitive(t, &p, "entry", &["a", "b"], &[]);
|
||||
assert_normal(t, &p, "a", &[]);
|
||||
assert_normal(t, &p, "b", &[]);
|
||||
|
||||
@ -645,7 +645,7 @@ fn deno_001() {
|
||||
|
||||
dbg!(&p);
|
||||
|
||||
assert_normal(t, &p, "main", &["http-server"]);
|
||||
assert_normal_transitive(t, &p, "main", &["http-server"], &["io-bufio"]);
|
||||
assert_normal(t, &p, "io-bufio", &[]);
|
||||
|
||||
assert_circular(t, &p, "http-server", &["_io"]);
|
||||
@ -702,6 +702,7 @@ fn circular_002() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Not deterministic yet"]
|
||||
fn deno_002() {
|
||||
suite()
|
||||
.file(
|
||||
@ -907,6 +908,7 @@ fn circular_root_entry_2() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Not deterministic yet"]
|
||||
fn deno_003() {
|
||||
suite()
|
||||
.file(
|
||||
|
@ -2,9 +2,10 @@ use super::load::TransformedModule;
|
||||
use crate::{Bundler, Load, Resolve};
|
||||
use anyhow::Error;
|
||||
use std::mem::take;
|
||||
use swc_atoms::js_word;
|
||||
use swc_common::DUMMY_SP;
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_utils::{find_ids, ExprFactory};
|
||||
use swc_ecma_utils::{find_ids, private_ident, ExprFactory};
|
||||
use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
|
||||
|
||||
impl<L, R> Bundler<'_, L, R>
|
||||
@ -113,13 +114,22 @@ impl Fold for ExportToReturn {
|
||||
let stmt = match decl {
|
||||
ModuleDecl::Import(_) => None,
|
||||
ModuleDecl::ExportDecl(export) => {
|
||||
let ids: Vec<Ident> = find_ids(&export.decl);
|
||||
self.exports.extend(
|
||||
ids.into_iter()
|
||||
.map(Prop::Shorthand)
|
||||
.map(Box::new)
|
||||
.map(PropOrSpread::Prop),
|
||||
);
|
||||
match &export.decl {
|
||||
Decl::Class(ClassDecl { ident, .. }) | Decl::Fn(FnDecl { ident, .. }) => {
|
||||
self.exports
|
||||
.push(PropOrSpread::Prop(Box::new(Prop::Shorthand(ident.clone()))));
|
||||
}
|
||||
Decl::Var(decl) => {
|
||||
let ids: Vec<Ident> = find_ids(decl);
|
||||
self.exports.extend(
|
||||
ids.into_iter()
|
||||
.map(Prop::Shorthand)
|
||||
.map(Box::new)
|
||||
.map(PropOrSpread::Prop),
|
||||
);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
Some(Stmt::Decl(export.decl))
|
||||
}
|
||||
@ -138,7 +148,41 @@ impl Fold for ExportToReturn {
|
||||
|
||||
None
|
||||
}
|
||||
ModuleDecl::ExportDefaultDecl(_) => None,
|
||||
ModuleDecl::ExportDefaultDecl(export) => match export.decl {
|
||||
DefaultDecl::Class(expr) => {
|
||||
let ident = expr.ident;
|
||||
let ident = ident.unwrap_or_else(|| private_ident!("_default_decl"));
|
||||
|
||||
self.exports
|
||||
.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new(js_word!("default"), export.span)),
|
||||
value: Box::new(Expr::Ident(ident.clone())),
|
||||
}))));
|
||||
|
||||
Some(Stmt::Decl(Decl::Class(ClassDecl {
|
||||
ident,
|
||||
class: expr.class,
|
||||
declare: false,
|
||||
})))
|
||||
}
|
||||
DefaultDecl::Fn(expr) => {
|
||||
let ident = expr.ident;
|
||||
let ident = ident.unwrap_or_else(|| private_ident!("_default_decl"));
|
||||
|
||||
self.exports
|
||||
.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(Ident::new(js_word!("default"), export.span)),
|
||||
value: Box::new(Expr::Ident(ident.clone())),
|
||||
}))));
|
||||
|
||||
Some(Stmt::Decl(Decl::Fn(FnDecl {
|
||||
ident,
|
||||
function: expr.function,
|
||||
declare: false,
|
||||
})))
|
||||
}
|
||||
DefaultDecl::TsInterfaceDecl(_) => None,
|
||||
},
|
||||
ModuleDecl::ExportDefaultExpr(_) => None,
|
||||
ModuleDecl::ExportAll(_) => {
|
||||
unimplemented!("export * from 'foo' inside a module loaded with computed key")
|
||||
|
@ -223,12 +223,16 @@ where
|
||||
})
|
||||
.unwrap_or_else(Vec::new);
|
||||
|
||||
let new_import = ImportDecl {
|
||||
specifiers,
|
||||
..import
|
||||
};
|
||||
if !specifiers.is_empty() {
|
||||
let new_import = ImportDecl {
|
||||
specifiers,
|
||||
..import
|
||||
};
|
||||
|
||||
return new_import;
|
||||
return new_import;
|
||||
}
|
||||
|
||||
self.info.forced_ns.insert(import.src.value.clone());
|
||||
}
|
||||
|
||||
_ => {}
|
||||
@ -304,6 +308,28 @@ where
|
||||
s
|
||||
}
|
||||
|
||||
fn fold_prop(&mut self, mut prop: Prop) -> Prop {
|
||||
prop = prop.fold_children_with(self);
|
||||
|
||||
match prop {
|
||||
Prop::Shorthand(mut i) => {
|
||||
if let Some(&ctxt) = self.imported_idents.get(&i.to_id()) {
|
||||
let local = i.clone();
|
||||
|
||||
i.span = i.span.with_ctxt(ctxt);
|
||||
|
||||
return Prop::KeyValue(KeyValueProp {
|
||||
key: PropName::Ident(local),
|
||||
value: Box::new(Expr::Ident(i)),
|
||||
});
|
||||
}
|
||||
|
||||
Prop::Shorthand(i)
|
||||
}
|
||||
_ => prop,
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_expr(&mut self, e: Expr) -> Expr {
|
||||
match e {
|
||||
Expr::Ident(mut i) if self.deglob_phase => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use self::scope::Scope;
|
||||
use crate::{Load, ModuleId, Resolve};
|
||||
use crate::{Hook, Load, ModuleId, Resolve};
|
||||
use anyhow::{Context, Error};
|
||||
use std::collections::HashMap;
|
||||
use swc_atoms::JsWord;
|
||||
@ -69,6 +69,8 @@ where
|
||||
_helper_ctxt: SyntaxContext,
|
||||
|
||||
scope: Scope,
|
||||
|
||||
hook: Box<dyn 'a + Hook>,
|
||||
}
|
||||
|
||||
impl<'a, L, R> Bundler<'a, L, R>
|
||||
@ -82,6 +84,7 @@ where
|
||||
loader: L,
|
||||
resolver: R,
|
||||
config: Config,
|
||||
hook: Box<dyn 'a + Hook>,
|
||||
) -> Self {
|
||||
GLOBALS.set(&globals, || {
|
||||
let used_mark = Mark::fresh(Mark::root());
|
||||
@ -98,6 +101,7 @@ where
|
||||
used_mark,
|
||||
_helper_ctxt: helper_ctxt,
|
||||
scope: Default::default(),
|
||||
hook,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use super::{load::TransformedModule, Bundler, Config};
|
||||
use crate::{util::HygieneRemover, Load, ModuleId, Resolve};
|
||||
use anyhow::Error;
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
use swc_common::{sync::Lrc, FileName, SourceFile, SourceMap, GLOBALS};
|
||||
use swc_common::{sync::Lrc, FileName, SourceFile, SourceMap, Span, GLOBALS};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_parser::{lexer::Lexer, JscTarget, Parser, StringInput};
|
||||
use swc_ecma_utils::drop_span;
|
||||
@ -131,6 +131,7 @@ impl TestBuilder {
|
||||
disable_inliner: true,
|
||||
external_modules: vec![],
|
||||
},
|
||||
Box::new(Hook),
|
||||
);
|
||||
|
||||
let mut t = Tester {
|
||||
@ -146,3 +147,11 @@ impl TestBuilder {
|
||||
.expect("WTF?");
|
||||
}
|
||||
}
|
||||
|
||||
struct Hook;
|
||||
|
||||
impl crate::Hook for Hook {
|
||||
fn get_import_meta_url(&self, _: Span, _: &FileName) -> Result<Option<Expr>, Error> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
9
bundler/src/hook.rs
Normal file
9
bundler/src/hook.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use anyhow::Error;
|
||||
use swc_common::{FileName, Span};
|
||||
use swc_ecma_ast::Expr;
|
||||
|
||||
/// Note: As this is rarely used, it's recommended to pass it as a trait object.
|
||||
pub trait Hook: swc_common::sync::Sync + swc_common::sync::Send {
|
||||
/// Return [None] to preserve `import.meta.url`
|
||||
fn get_import_meta_url(&self, span: Span, file: &FileName) -> Result<Option<Expr>, Error>;
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
#![deny(unused)]
|
||||
|
||||
pub use self::{
|
||||
bundler::{Bundle, BundleKind, Bundler, Config},
|
||||
hook::Hook,
|
||||
id::ModuleId,
|
||||
load::Load,
|
||||
resolve::Resolve,
|
||||
@ -10,6 +9,7 @@ pub use self::{
|
||||
mod bundler;
|
||||
mod debug;
|
||||
mod hash;
|
||||
mod hook;
|
||||
mod id;
|
||||
mod load;
|
||||
mod resolve;
|
||||
|
123
bundler/tests/deno.rs
Normal file
123
bundler/tests/deno.rs
Normal file
@ -0,0 +1,123 @@
|
||||
//! In-tree testing for deno integration.
|
||||
//!
|
||||
//! This module exists because this is way easier than using copying requires
|
||||
//! files.
|
||||
|
||||
use anyhow::{Context, Error};
|
||||
use std::collections::HashMap;
|
||||
use swc_bundler::{Bundler, Load, Resolve};
|
||||
use swc_common::{sync::Lrc, FileName, SourceFile, SourceMap, Span, GLOBALS};
|
||||
use swc_ecma_ast::{Expr, Lit, Module, Str};
|
||||
use swc_ecma_parser::{lexer::Lexer, JscTarget, Parser, StringInput, Syntax, TsConfig};
|
||||
use swc_ecma_transforms::typescript::strip;
|
||||
use swc_ecma_visit::FoldWith;
|
||||
use url::Url;
|
||||
|
||||
#[test]
|
||||
#[ignore = "Too slow"]
|
||||
fn oak_6_2_0_application() {
|
||||
bundle("https://deno.land/x/oak@v6.2.0/mod.ts");
|
||||
}
|
||||
|
||||
fn bundle(url: &str) -> Module {
|
||||
let result = testing::run_test2(false, |cm, _handler| {
|
||||
GLOBALS.with(|globals| {
|
||||
let bundler = Bundler::new(
|
||||
globals,
|
||||
cm.clone(),
|
||||
Loader { cm: cm.clone() },
|
||||
Resolver,
|
||||
swc_bundler::Config {
|
||||
require: false,
|
||||
disable_inliner: true,
|
||||
..Default::default()
|
||||
},
|
||||
Box::new(Hook),
|
||||
);
|
||||
let mut entries = HashMap::new();
|
||||
entries.insert("main".to_string(), FileName::Custom(url.to_string()));
|
||||
let output = bundler.bundle(entries).unwrap();
|
||||
|
||||
Ok(output.into_iter().next().unwrap().module)
|
||||
})
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Loader {
|
||||
cm: Lrc<SourceMap>,
|
||||
}
|
||||
|
||||
impl Load for Loader {
|
||||
fn load(&self, file: &FileName) -> Result<(Lrc<SourceFile>, Module), Error> {
|
||||
let url = match file {
|
||||
FileName::Custom(v) => v,
|
||||
_ => unreachable!("this test only uses url"),
|
||||
};
|
||||
|
||||
let url = Url::parse(&url).context("failed to parse url")?;
|
||||
let resp = reqwest::blocking::get(url.clone())
|
||||
.with_context(|| format!("failed to fetch `{}`", url))?;
|
||||
|
||||
let bytes = resp
|
||||
.bytes()
|
||||
.with_context(|| format!("failed to read data from `{}`", url))?;
|
||||
|
||||
let src = String::from_utf8_lossy(&bytes);
|
||||
let fm = self
|
||||
.cm
|
||||
.new_source_file(FileName::Custom(url.to_string()), src.to_string());
|
||||
|
||||
let lexer = Lexer::new(
|
||||
Syntax::Typescript(TsConfig {
|
||||
decorators: true,
|
||||
..Default::default()
|
||||
}),
|
||||
JscTarget::Es2020,
|
||||
StringInput::from(&*fm),
|
||||
None,
|
||||
);
|
||||
|
||||
let mut parser = Parser::new_from(lexer);
|
||||
let module = parser.parse_typescript_module().unwrap();
|
||||
let module = module.fold_with(&mut strip());
|
||||
|
||||
Ok((fm, module))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct Resolver;
|
||||
|
||||
impl Resolve for Resolver {
|
||||
fn resolve(&self, base: &FileName, module_specifier: &str) -> Result<FileName, Error> {
|
||||
let base_url = match base {
|
||||
FileName::Custom(v) => v,
|
||||
_ => unreachable!("this test only uses url"),
|
||||
};
|
||||
let base_url = Url::parse(&base_url).context("failed to parse url")?;
|
||||
|
||||
let options = Url::options();
|
||||
let base_url = options.base_url(Some(&base_url));
|
||||
let url = base_url
|
||||
.parse(module_specifier)
|
||||
.with_context(|| format!("failed to resolve `{}`", module_specifier))?;
|
||||
|
||||
return Ok(FileName::Custom(url.to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
struct Hook;
|
||||
|
||||
impl swc_bundler::Hook for Hook {
|
||||
fn get_import_meta_url(&self, span: Span, file: &FileName) -> Result<Option<Expr>, Error> {
|
||||
Ok(Some(Expr::Lit(Lit::Str(Str {
|
||||
span,
|
||||
value: file.to_string().into(),
|
||||
has_escape: false,
|
||||
}))))
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ edition = "2018"
|
||||
license = "Apache-2.0/MIT"
|
||||
name = "swc_ecmascript"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
|
||||
[features]
|
||||
codegen = ["swc_ecma_codegen"]
|
||||
|
@ -144,7 +144,7 @@
|
||||
),
|
||||
ctxt: #0,
|
||||
},
|
||||
value: Atom('url' type=inline),
|
||||
value: Atom('url' type=static),
|
||||
},
|
||||
},
|
||||
),
|
||||
|
@ -6,7 +6,7 @@ edition = "2018"
|
||||
license = "Apache-2.0/MIT"
|
||||
name = "swc_ecma_transforms"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
version = "0.24.2"
|
||||
version = "0.24.3"
|
||||
|
||||
[features]
|
||||
const-modules = ["dashmap"]
|
||||
|
@ -702,6 +702,8 @@ impl<'a> VisitMut for Hygiene<'a> {
|
||||
self.visit_mut_fn(node.ident.clone(), &mut node.function);
|
||||
}
|
||||
|
||||
fn visit_mut_private_name(&mut self, _: &mut PrivateName) {}
|
||||
|
||||
/// Invoked for `IdetifierRefrence` / `BindingIdentifier`
|
||||
fn visit_mut_ident(&mut self, i: &mut Ident) {
|
||||
if i.sym == js_word!("arguments") || i.sym == js_word!("undefined") {
|
||||
|
@ -889,6 +889,8 @@ impl<'a> VisitMut for Resolver<'a> {
|
||||
f.return_type.visit_mut_with(self);
|
||||
}
|
||||
|
||||
fn visit_mut_private_name(&mut self, _: &mut PrivateName) {}
|
||||
|
||||
fn visit_mut_ident(&mut self, i: &mut Ident) {
|
||||
let ident_type = self.ident_type;
|
||||
let in_type = self.in_type;
|
||||
|
@ -521,3 +521,30 @@ let X = ((_class = class X {
|
||||
}), _class);
|
||||
export { X as default };"
|
||||
);
|
||||
|
||||
test!(
|
||||
Syntax::Typescript(TsConfig {
|
||||
decorators: true,
|
||||
..Default::default()
|
||||
}),
|
||||
|_| chain!(
|
||||
resolver(),
|
||||
typescript::strip(),
|
||||
decorators(decorators::Config {
|
||||
legacy: true,
|
||||
emit_metadata: false
|
||||
}),
|
||||
dce(Default::default())
|
||||
),
|
||||
issue_1111,
|
||||
"
|
||||
const a = 1;
|
||||
export const d = { a };
|
||||
",
|
||||
"
|
||||
const a = 1;
|
||||
export const d = {
|
||||
a
|
||||
};
|
||||
"
|
||||
);
|
||||
|
@ -2,7 +2,7 @@ use crate::{
|
||||
get_compiler,
|
||||
util::{CtxtExt, MapErr},
|
||||
};
|
||||
use anyhow::bail;
|
||||
use anyhow::{bail, Error};
|
||||
use fxhash::FxHashMap;
|
||||
use napi::{CallContext, Env, JsObject, Status, Task};
|
||||
use serde::Deserialize;
|
||||
@ -13,6 +13,8 @@ use std::{
|
||||
};
|
||||
use swc::{config::SourceMapsConfig, Compiler, TransformOutput};
|
||||
use swc_bundler::{BundleKind, Bundler, Load, Resolve};
|
||||
use swc_common::{FileName, Span};
|
||||
use swc_ecma_ast::{Expr, Lit, Str};
|
||||
|
||||
struct ConfigItem {
|
||||
loader: Box<dyn Load>,
|
||||
@ -87,6 +89,7 @@ impl Task for BundleTask {
|
||||
.collect(),
|
||||
..Default::default()
|
||||
},
|
||||
Box::new(Hook),
|
||||
);
|
||||
|
||||
let result = bundler
|
||||
@ -182,3 +185,15 @@ pub(crate) fn bundle(cx: CallContext) -> napi::Result<JsObject> {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
struct Hook;
|
||||
|
||||
impl swc_bundler::Hook for Hook {
|
||||
fn get_import_meta_url(&self, span: Span, file: &FileName) -> Result<Option<Expr>, Error> {
|
||||
Ok(Some(Expr::Lit(Lit::Str(Str {
|
||||
span,
|
||||
value: file.to_string().into(),
|
||||
has_escape: false,
|
||||
}))))
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
extern crate test;
|
||||
|
||||
use anyhow::Error;
|
||||
use spack::{loaders::swc::SwcLoader, resolvers::NodeResolver};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
@ -13,7 +14,8 @@ use std::{
|
||||
};
|
||||
use swc::config::SourceMapsConfig;
|
||||
use swc_bundler::{BundleKind, Bundler, Config};
|
||||
use swc_common::{FileName, GLOBALS};
|
||||
use swc_common::{FileName, Span, GLOBALS};
|
||||
use swc_ecma_ast::{Expr, Lit, Str};
|
||||
use swc_ecma_transforms::fixer;
|
||||
use swc_ecma_visit::FoldWith;
|
||||
use test::{
|
||||
@ -176,6 +178,7 @@ fn reference_tests(tests: &mut Vec<TestDescAndFn>, errors: bool) -> Result<(), i
|
||||
.map(From::from)
|
||||
.collect(),
|
||||
},
|
||||
Box::new(Hook),
|
||||
);
|
||||
|
||||
let modules = bundler
|
||||
@ -253,3 +256,15 @@ fn errors() {
|
||||
reference_tests(&mut tests, true).unwrap();
|
||||
test_main(&args, tests, Some(Options::new()));
|
||||
}
|
||||
|
||||
struct Hook;
|
||||
|
||||
impl swc_bundler::Hook for Hook {
|
||||
fn get_import_meta_url(&self, span: Span, file: &FileName) -> Result<Option<Expr>, Error> {
|
||||
Ok(Some(Expr::Lit(Lit::Str(Str {
|
||||
span,
|
||||
value: file.to_string().into(),
|
||||
has_escape: false,
|
||||
}))))
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,8 @@ class MuxAsyncIterator {
|
||||
this.signal = deferred();
|
||||
}
|
||||
}
|
||||
const MuxAsyncIterator1 = MuxAsyncIterator, deferred1 = deferred;
|
||||
const MuxAsyncIterator1 = MuxAsyncIterator;
|
||||
const deferred1 = deferred;
|
||||
class ServerRequest {
|
||||
/**
|
||||
* Value of Content-Length header.
|
||||
|
@ -51,7 +51,8 @@ class MuxAsyncIterator {
|
||||
this.signal = deferred();
|
||||
}
|
||||
}
|
||||
const deferred1 = deferred, MuxAsyncIterator1 = MuxAsyncIterator;
|
||||
const MuxAsyncIterator1 = MuxAsyncIterator;
|
||||
const deferred1 = deferred;
|
||||
class ServerRequest {
|
||||
/**
|
||||
* Value of Content-Length header.
|
||||
|
@ -5,7 +5,8 @@ class MuxAsyncIterator {
|
||||
this.signal = deferred();
|
||||
}
|
||||
}
|
||||
const deferred1 = deferred, MuxAsyncIterator1 = MuxAsyncIterator;
|
||||
const MuxAsyncIterator1 = MuxAsyncIterator;
|
||||
const deferred1 = deferred;
|
||||
console.log(deferred1, writeResponse, readRequest, MuxAsyncIterator1);
|
||||
class ServerRequest {
|
||||
constructor(){
|
||||
|
@ -5,5 +5,6 @@ class MuxAsyncIterator {
|
||||
this.signal = deferred();
|
||||
}
|
||||
}
|
||||
const MuxAsyncIterator1 = MuxAsyncIterator, deferred1 = deferred;
|
||||
const MuxAsyncIterator1 = MuxAsyncIterator;
|
||||
const deferred1 = deferred;
|
||||
console.log(deferred1, MuxAsyncIterator1);
|
||||
|
@ -1,7 +1,7 @@
|
||||
function deferred() {
|
||||
}
|
||||
const deferred1 = deferred;
|
||||
function MuxAsyncIterator() {
|
||||
}
|
||||
const MuxAsyncIterator1 = MuxAsyncIterator;
|
||||
const deferred1 = deferred;
|
||||
console.log(deferred1, MuxAsyncIterator1);
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "typescript",
|
||||
"dynamicImport": true
|
||||
},
|
||||
"target": "es2020"
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
export const a = 1;
|
@ -0,0 +1,3 @@
|
||||
const a = await import("./a.ts");
|
||||
|
||||
console.log(a);
|
@ -0,0 +1,2 @@
|
||||
const a = await import("./a.ts");
|
||||
console.log(a);
|
7
spack/tests/pass/export-star-namespace/issue-1109/.swcrc
Normal file
7
spack/tests/pass/export-star-namespace/issue-1109/.swcrc
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "typescript"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
export const a = 1
|
@ -0,0 +1 @@
|
||||
export * as a from './a';
|
@ -0,0 +1,7 @@
|
||||
const _a = function() {
|
||||
var a = 1;
|
||||
return {
|
||||
a
|
||||
};
|
||||
}();
|
||||
export { _a as a };
|
1
spack/tests/pass/export/issue-1111/simple/input/a.js
Normal file
1
spack/tests/pass/export/issue-1111/simple/input/a.js
Normal file
@ -0,0 +1 @@
|
||||
export const a = "a";
|
3
spack/tests/pass/export/issue-1111/simple/input/d.js
Normal file
3
spack/tests/pass/export/issue-1111/simple/input/d.js
Normal file
@ -0,0 +1,3 @@
|
||||
import { a } from "./a";
|
||||
|
||||
export const d = { a };
|
3
spack/tests/pass/export/issue-1111/simple/input/entry.js
Normal file
3
spack/tests/pass/export/issue-1111/simple/input/entry.js
Normal file
@ -0,0 +1,3 @@
|
||||
import { d } from "./d";
|
||||
|
||||
console.log(d);
|
@ -0,0 +1,5 @@
|
||||
const a = "a";
|
||||
const d = {
|
||||
a: a
|
||||
};
|
||||
console.log(d);
|
3
spack/tests/pass/import/star-export/input/a.js
Normal file
3
spack/tests/pass/import/star-export/input/a.js
Normal file
@ -0,0 +1,3 @@
|
||||
export class A {
|
||||
|
||||
}
|
4
spack/tests/pass/import/star-export/input/entry.js
Normal file
4
spack/tests/pass/import/star-export/input/entry.js
Normal file
@ -0,0 +1,4 @@
|
||||
import * as _a from './a';
|
||||
|
||||
|
||||
export { _a as a }
|
8
spack/tests/pass/import/star-export/output/entry.js
Normal file
8
spack/tests/pass/import/star-export/output/entry.js
Normal file
@ -0,0 +1,8 @@
|
||||
const _a = function() {
|
||||
class A {
|
||||
}
|
||||
return {
|
||||
A
|
||||
};
|
||||
}();
|
||||
export { _a as a };
|
3
spack/tests/pass/import/star-use/input/a.js
Normal file
3
spack/tests/pass/import/star-use/input/a.js
Normal file
@ -0,0 +1,3 @@
|
||||
export class A {
|
||||
|
||||
}
|
3
spack/tests/pass/import/star-use/input/entry.js
Normal file
3
spack/tests/pass/import/star-use/input/entry.js
Normal file
@ -0,0 +1,3 @@
|
||||
import * as a from './a';
|
||||
|
||||
console.log(a)
|
8
spack/tests/pass/import/star-use/output/entry.js
Normal file
8
spack/tests/pass/import/star-use/output/entry.js
Normal file
@ -0,0 +1,8 @@
|
||||
const a = function() {
|
||||
class A {
|
||||
}
|
||||
return {
|
||||
A
|
||||
};
|
||||
}();
|
||||
console.log(a);
|
1
spack/tests/pass/pr-1105/example-1/input/a.js
Normal file
1
spack/tests/pass/pr-1105/example-1/input/a.js
Normal file
@ -0,0 +1 @@
|
||||
export const a = "a";
|
3
spack/tests/pass/pr-1105/example-1/input/entry.js
Normal file
3
spack/tests/pass/pr-1105/example-1/input/entry.js
Normal file
@ -0,0 +1,3 @@
|
||||
import * as a from "./a";
|
||||
|
||||
console.log(a); // { a: "a" }
|
7
spack/tests/pass/pr-1105/example-1/output/entry.js
Normal file
7
spack/tests/pass/pr-1105/example-1/output/entry.js
Normal file
@ -0,0 +1,7 @@
|
||||
const a = function() {
|
||||
const a = "a";
|
||||
return {
|
||||
a
|
||||
};
|
||||
}();
|
||||
console.log(a); // { a: "a" }
|
8
spack/tests/pass/pr-1105/example-10/input/.swcrc
Normal file
8
spack/tests/pass/pr-1105/example-10/input/.swcrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"jsc": {
|
||||
"target": "es2020",
|
||||
"parser": {
|
||||
"syntax": "typescript"
|
||||
}
|
||||
}
|
||||
}
|
1
spack/tests/pass/pr-1105/example-10/input/entry.js
Normal file
1
spack/tests/pass/pr-1105/example-10/input/entry.js
Normal file
@ -0,0 +1 @@
|
||||
export { a, b } from "./k";
|
3
spack/tests/pass/pr-1105/example-10/input/i.ts
Normal file
3
spack/tests/pass/pr-1105/example-10/input/i.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export function a(...d: string[]): string {
|
||||
return d.join(" ");
|
||||
}
|
3
spack/tests/pass/pr-1105/example-10/input/j.ts
Normal file
3
spack/tests/pass/pr-1105/example-10/input/j.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export function a(...d: string[]): string {
|
||||
return d.join("/");
|
||||
}
|
11
spack/tests/pass/pr-1105/example-10/input/k.ts
Normal file
11
spack/tests/pass/pr-1105/example-10/input/k.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import * as _i from "./i";
|
||||
import * as _j from "./j";
|
||||
|
||||
const k = globalThis.value ? _i : _j;
|
||||
|
||||
export const i = _i;
|
||||
export const j = _j;
|
||||
|
||||
export const {
|
||||
a,
|
||||
} = k;
|
19
spack/tests/pass/pr-1105/example-10/output/entry.js
Normal file
19
spack/tests/pass/pr-1105/example-10/output/entry.js
Normal file
@ -0,0 +1,19 @@
|
||||
const _i = function() {
|
||||
function a(...d) {
|
||||
return d.join(" ");
|
||||
}
|
||||
return {
|
||||
a
|
||||
};
|
||||
}();
|
||||
const _j = function() {
|
||||
function a(...d) {
|
||||
return d.join("/");
|
||||
}
|
||||
return {
|
||||
a
|
||||
};
|
||||
}();
|
||||
const k = globalThis.value ? _i : _j;
|
||||
const { a , } = k;
|
||||
export { a, b };
|
9
spack/tests/pass/pr-1105/example-2/input/.swcrc
Normal file
9
spack/tests/pass/pr-1105/example-2/input/.swcrc
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"jsc": {
|
||||
"target": "es2020",
|
||||
"parser": {
|
||||
"syntax": "ecmascript",
|
||||
"exportNamespaceFrom": true
|
||||
}
|
||||
}
|
||||
}
|
3
spack/tests/pass/pr-1105/example-2/input/b.js
Normal file
3
spack/tests/pass/pr-1105/example-2/input/b.js
Normal file
@ -0,0 +1,3 @@
|
||||
export * as c from "./c";
|
||||
|
||||
export const b = "b";
|
2
spack/tests/pass/pr-1105/example-2/input/c.js
Normal file
2
spack/tests/pass/pr-1105/example-2/input/c.js
Normal file
@ -0,0 +1,2 @@
|
||||
export const c = "c";
|
||||
export default class C { }
|
4
spack/tests/pass/pr-1105/example-2/input/entry.js
Normal file
4
spack/tests/pass/pr-1105/example-2/input/entry.js
Normal file
@ -0,0 +1,4 @@
|
||||
import * as b from "./b";
|
||||
|
||||
console.log(b.b); // "b"
|
||||
console.log(b.c); // { c: "c", default: class C }
|
13
spack/tests/pass/pr-1105/example-2/output/entry.js
Normal file
13
spack/tests/pass/pr-1105/example-2/output/entry.js
Normal file
@ -0,0 +1,13 @@
|
||||
const _c = function() {
|
||||
const c = "c";
|
||||
class C {
|
||||
}
|
||||
return {
|
||||
c,
|
||||
default: C
|
||||
};
|
||||
}();
|
||||
const c = _c;
|
||||
const b = "b";
|
||||
console.log(b); // "b"
|
||||
console.log(c); // { c: "c", default: class C }
|
1
spack/tests/pass/pr-1105/example-3/input/a.js
Normal file
1
spack/tests/pass/pr-1105/example-3/input/a.js
Normal file
@ -0,0 +1 @@
|
||||
export const a = "a";
|
3
spack/tests/pass/pr-1105/example-3/input/d.js
Normal file
3
spack/tests/pass/pr-1105/example-3/input/d.js
Normal file
@ -0,0 +1,3 @@
|
||||
import { a } from "./a";
|
||||
|
||||
export const d = { a };
|
3
spack/tests/pass/pr-1105/example-3/input/entry.js
Normal file
3
spack/tests/pass/pr-1105/example-3/input/entry.js
Normal file
@ -0,0 +1,3 @@
|
||||
import { d } from "./d";
|
||||
|
||||
console.log(d);
|
5
spack/tests/pass/pr-1105/example-3/output/entry.js
Normal file
5
spack/tests/pass/pr-1105/example-3/output/entry.js
Normal file
@ -0,0 +1,5 @@
|
||||
const a = "a";
|
||||
const d = {
|
||||
a: a
|
||||
};
|
||||
console.log(d);
|
1
spack/tests/pass/pr-1105/example-5/input/a.js
Normal file
1
spack/tests/pass/pr-1105/example-5/input/a.js
Normal file
@ -0,0 +1 @@
|
||||
export const a = "a";
|
1
spack/tests/pass/pr-1105/example-5/input/e.js
Normal file
1
spack/tests/pass/pr-1105/example-5/input/e.js
Normal file
@ -0,0 +1 @@
|
||||
export * from "./a";
|
3
spack/tests/pass/pr-1105/example-5/input/entry.js
Normal file
3
spack/tests/pass/pr-1105/example-5/input/entry.js
Normal file
@ -0,0 +1,3 @@
|
||||
import { a } from "./e";
|
||||
|
||||
console.log(a);
|
2
spack/tests/pass/pr-1105/example-5/output/entry.js
Normal file
2
spack/tests/pass/pr-1105/example-5/output/entry.js
Normal file
@ -0,0 +1,2 @@
|
||||
const a = "a";
|
||||
console.log(a);
|
8
spack/tests/pass/pr-1105/example-7/input/.swcrc
Normal file
8
spack/tests/pass/pr-1105/example-7/input/.swcrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"jsc": {
|
||||
"target": "es2020",
|
||||
"parser": {
|
||||
"syntax": "typescript"
|
||||
}
|
||||
}
|
||||
}
|
4
spack/tests/pass/pr-1105/example-7/input/entry.js
Normal file
4
spack/tests/pass/pr-1105/example-7/input/entry.js
Normal file
@ -0,0 +1,4 @@
|
||||
import { isMain, modUrl } from "./f";
|
||||
|
||||
console.log(isMain, modUrl);
|
||||
console.log(import.meta.main, import.meta.url);
|
2
spack/tests/pass/pr-1105/example-7/input/f.js
Normal file
2
spack/tests/pass/pr-1105/example-7/input/f.js
Normal file
@ -0,0 +1,2 @@
|
||||
export const isMain = import.meta.main;
|
||||
export const modUrl = import.meta.url;
|
4
spack/tests/pass/pr-1105/example-7/output/entry.js
Normal file
4
spack/tests/pass/pr-1105/example-7/output/entry.js
Normal file
@ -0,0 +1,4 @@
|
||||
const isMain = false;
|
||||
const modUrl = "$DIR/tests/pass/pr-1105/example-7/input/f.js";
|
||||
console.log(isMain, modUrl);
|
||||
console.log(import.meta.main, "$DIR/tests/pass/pr-1105/example-7/input/entry.js");
|
8
spack/tests/pass/pr-1105/example-9-js/input/.swcrc
Normal file
8
spack/tests/pass/pr-1105/example-9-js/input/.swcrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "ecmascript",
|
||||
"exportNamespaceFrom": true
|
||||
}
|
||||
}
|
||||
}
|
1
spack/tests/pass/pr-1105/example-9-js/input/a.js
Normal file
1
spack/tests/pass/pr-1105/example-9-js/input/a.js
Normal file
@ -0,0 +1 @@
|
||||
export const a = "a";
|
1
spack/tests/pass/pr-1105/example-9-js/input/entry.js
Normal file
1
spack/tests/pass/pr-1105/example-9-js/input/entry.js
Normal file
@ -0,0 +1 @@
|
||||
export * as a from "./a";
|
7
spack/tests/pass/pr-1105/example-9-js/output/entry.js
Normal file
7
spack/tests/pass/pr-1105/example-9-js/output/entry.js
Normal file
@ -0,0 +1,7 @@
|
||||
const _a = function() {
|
||||
var a = "a";
|
||||
return {
|
||||
a
|
||||
};
|
||||
}();
|
||||
export { _a as a };
|
7
spack/tests/pass/pr-1105/example-9-ts/input/.swcrc
Normal file
7
spack/tests/pass/pr-1105/example-9-ts/input/.swcrc
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"jsc": {
|
||||
"parser": {
|
||||
"syntax": "typescript"
|
||||
}
|
||||
}
|
||||
}
|
1
spack/tests/pass/pr-1105/example-9-ts/input/a.ts
Normal file
1
spack/tests/pass/pr-1105/example-9-ts/input/a.ts
Normal file
@ -0,0 +1 @@
|
||||
export const a = "a";
|
1
spack/tests/pass/pr-1105/example-9-ts/input/entry.js
Normal file
1
spack/tests/pass/pr-1105/example-9-ts/input/entry.js
Normal file
@ -0,0 +1 @@
|
||||
export * as a from "./a";
|
7
spack/tests/pass/pr-1105/example-9-ts/output/entry.js
Normal file
7
spack/tests/pass/pr-1105/example-9-ts/output/entry.js
Normal file
@ -0,0 +1,7 @@
|
||||
const _a = function() {
|
||||
var a = "a";
|
||||
return {
|
||||
a
|
||||
};
|
||||
}();
|
||||
export { _a as a };
|
Loading…
Reference in New Issue
Block a user