mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
feat(repl): support exports in the REPL (#11592)
This commit is contained in:
parent
15b0e61de5
commit
e9ddc7a41a
3 changed files with 195 additions and 24 deletions
|
@ -314,6 +314,7 @@ impl ParsedModule {
|
|||
let mut passes = chain!(
|
||||
Optional::new(jsx_pass, options.transform_jsx),
|
||||
Optional::new(transforms::DownlevelImportsFolder, options.repl_imports),
|
||||
Optional::new(transforms::StripExportsFolder, options.repl_imports),
|
||||
proposals::decorators::decorators(proposals::decorators::Config {
|
||||
legacy: true,
|
||||
emit_metadata: options.emit_metadata
|
||||
|
|
|
@ -21,33 +21,12 @@ impl Fold for DownlevelImportsFolder {
|
|||
ModuleItem::ModuleDecl(ModuleDecl::Import(import_decl)) => {
|
||||
// Handle type only imports
|
||||
if import_decl.type_only {
|
||||
return ModuleItem::Stmt(Stmt::Empty(EmptyStmt { span: DUMMY_SP }));
|
||||
// should have no side effects
|
||||
return create_empty_stmt();
|
||||
}
|
||||
|
||||
// The initializer (ex. `await import('./mod.ts')`)
|
||||
let initializer = Box::new(Expr::Await(AwaitExpr {
|
||||
span: DUMMY_SP,
|
||||
arg: Box::new(Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: ExprOrSuper::Expr(Box::new(Expr::Ident(Ident {
|
||||
span: DUMMY_SP,
|
||||
sym: "import".into(),
|
||||
optional: false,
|
||||
}))),
|
||||
args: vec![ExprOrSpread {
|
||||
spread: None,
|
||||
expr: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
span: DUMMY_SP,
|
||||
has_escape: false,
|
||||
kind: StrKind::Normal {
|
||||
contains_quote: false,
|
||||
},
|
||||
value: import_decl.src.value.clone(),
|
||||
}))),
|
||||
}],
|
||||
type_args: None,
|
||||
})),
|
||||
}));
|
||||
let initializer = create_await_import_expr(&import_decl.src.value);
|
||||
|
||||
// Handle imports for the side effects
|
||||
// ex. `import "module.ts"` -> `await import("module.ts");`
|
||||
|
@ -128,6 +107,78 @@ impl Fold for DownlevelImportsFolder {
|
|||
}
|
||||
}
|
||||
|
||||
/// Strips export declarations and exports on named exports for the REPL.
|
||||
pub struct StripExportsFolder;
|
||||
|
||||
impl Fold for StripExportsFolder {
|
||||
noop_fold_type!(); // skip typescript specific nodes
|
||||
|
||||
fn fold_module_item(
|
||||
&mut self,
|
||||
module_item: swc_ast::ModuleItem,
|
||||
) -> swc_ast::ModuleItem {
|
||||
use swc_ecmascript::ast::*;
|
||||
|
||||
match module_item {
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportAll(export_all)) => {
|
||||
ModuleItem::Stmt(Stmt::Expr(ExprStmt {
|
||||
span: DUMMY_SP,
|
||||
expr: create_await_import_expr(&export_all.src.value),
|
||||
}))
|
||||
}
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportNamed(export_named)) => {
|
||||
if let Some(src) = export_named.src {
|
||||
ModuleItem::Stmt(Stmt::Expr(ExprStmt {
|
||||
span: DUMMY_SP,
|
||||
expr: create_await_import_expr(&src.value),
|
||||
}))
|
||||
} else {
|
||||
create_empty_stmt()
|
||||
}
|
||||
}
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultExpr(default_expr)) => {
|
||||
// transform a default export expression to its expression
|
||||
ModuleItem::Stmt(Stmt::Expr(ExprStmt {
|
||||
span: DUMMY_SP,
|
||||
expr: default_expr.expr,
|
||||
}))
|
||||
}
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(export_decl)) => {
|
||||
// strip the export keyword on an exported declaration
|
||||
ModuleItem::Stmt(Stmt::Decl(export_decl.decl))
|
||||
}
|
||||
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(default_decl)) => {
|
||||
// only keep named default exports
|
||||
match default_decl.decl {
|
||||
DefaultDecl::Fn(FnExpr {
|
||||
ident: Some(ident),
|
||||
function,
|
||||
}) => ModuleItem::Stmt(Stmt::Decl(Decl::Fn(FnDecl {
|
||||
declare: false,
|
||||
ident,
|
||||
function,
|
||||
}))),
|
||||
DefaultDecl::Class(ClassExpr {
|
||||
ident: Some(ident),
|
||||
class,
|
||||
}) => ModuleItem::Stmt(Stmt::Decl(Decl::Class(ClassDecl {
|
||||
declare: false,
|
||||
ident,
|
||||
class,
|
||||
}))),
|
||||
_ => create_empty_stmt(),
|
||||
}
|
||||
}
|
||||
_ => module_item,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_empty_stmt() -> swc_ast::ModuleItem {
|
||||
use swc_ast::*;
|
||||
ModuleItem::Stmt(Stmt::Empty(EmptyStmt { span: DUMMY_SP }))
|
||||
}
|
||||
|
||||
fn create_binding_ident(name: String) -> swc_ast::BindingIdent {
|
||||
swc_ast::BindingIdent {
|
||||
id: create_ident(name),
|
||||
|
@ -161,6 +212,33 @@ fn create_key_value(key: String, value: String) -> swc_ast::ObjectPatProp {
|
|||
})
|
||||
}
|
||||
|
||||
fn create_await_import_expr(module_specifier: &str) -> Box<swc_ast::Expr> {
|
||||
use swc_ast::*;
|
||||
Box::new(Expr::Await(AwaitExpr {
|
||||
span: DUMMY_SP,
|
||||
arg: Box::new(Expr::Call(CallExpr {
|
||||
span: DUMMY_SP,
|
||||
callee: ExprOrSuper::Expr(Box::new(Expr::Ident(Ident {
|
||||
span: DUMMY_SP,
|
||||
sym: "import".into(),
|
||||
optional: false,
|
||||
}))),
|
||||
args: vec![ExprOrSpread {
|
||||
spread: None,
|
||||
expr: Box::new(Expr::Lit(Lit::Str(Str {
|
||||
span: DUMMY_SP,
|
||||
has_escape: false,
|
||||
kind: StrKind::Normal {
|
||||
contains_quote: false,
|
||||
},
|
||||
value: module_specifier.into(),
|
||||
}))),
|
||||
}],
|
||||
type_args: None,
|
||||
})),
|
||||
}))
|
||||
}
|
||||
|
||||
fn create_assignment(key: String) -> swc_ast::ObjectPatProp {
|
||||
swc_ast::ObjectPatProp::Assign(swc_ast::AssignPatProp {
|
||||
span: DUMMY_SP,
|
||||
|
@ -264,6 +342,85 @@ mod test {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strip_exports_export_all() {
|
||||
test_transform(
|
||||
StripExportsFolder,
|
||||
r#"export * from "./test.ts";"#,
|
||||
r#"await import("./test.ts");"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strip_exports_export_named() {
|
||||
test_transform(
|
||||
StripExportsFolder,
|
||||
r#"export { test } from "./test.ts";"#,
|
||||
r#"await import("./test.ts");"#,
|
||||
);
|
||||
|
||||
test_transform(StripExportsFolder, r#"export { test };"#, ";");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strip_exports_export_default_expr() {
|
||||
test_transform(StripExportsFolder, "export default 5;", "5;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strip_exports_export_default_decl_name() {
|
||||
test_transform(
|
||||
StripExportsFolder,
|
||||
"export default class Test {}",
|
||||
"class Test {\n}",
|
||||
);
|
||||
|
||||
test_transform(
|
||||
StripExportsFolder,
|
||||
"export default function test() {}",
|
||||
"function test() {\n}",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strip_exports_export_default_decl_no_name() {
|
||||
test_transform(StripExportsFolder, "export default class {}", ";");
|
||||
|
||||
test_transform(StripExportsFolder, "export default function() {}", ";");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strip_exports_export_named_decls() {
|
||||
test_transform(
|
||||
StripExportsFolder,
|
||||
"export class Test {}",
|
||||
"class Test {\n}",
|
||||
);
|
||||
|
||||
test_transform(
|
||||
StripExportsFolder,
|
||||
"export function test() {}",
|
||||
"function test() {\n}",
|
||||
);
|
||||
|
||||
test_transform(StripExportsFolder, "export enum Test {}", "enum Test {\n}");
|
||||
|
||||
test_transform(
|
||||
StripExportsFolder,
|
||||
"export namespace Test {}",
|
||||
"module Test {\n}",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strip_exports_not_in_namespace() {
|
||||
test_transform(
|
||||
StripExportsFolder,
|
||||
"namespace Test { export class Test {} }",
|
||||
"module Test {\n export class Test {\n }\n}",
|
||||
);
|
||||
}
|
||||
|
||||
fn test_transform(
|
||||
mut transform: impl Fold,
|
||||
src: &str,
|
||||
|
|
|
@ -422,6 +422,19 @@ fn import_declarations() {
|
|||
assert!(out.contains("hello!\n"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exports_stripped() {
|
||||
let (out, err) = util::run_and_collect_output(
|
||||
true,
|
||||
"repl",
|
||||
Some(vec!["export default 5;", "export class Test {}"]),
|
||||
Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]),
|
||||
false,
|
||||
);
|
||||
assert!(out.contains("5\n"));
|
||||
assert!(err.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eval_unterminated() {
|
||||
let (out, err) = util::run_and_collect_output(
|
||||
|
|
Loading…
Add table
Reference in a new issue