mirror of
https://github.com/denoland/deno.git
synced 2024-12-26 00:59:24 -05:00
parent
034ab48086
commit
57e95032c8
59 changed files with 886 additions and 67 deletions
70
Cargo.lock
generated
70
Cargo.lock
generated
|
@ -212,6 +212,12 @@ dependencies = [
|
|||
"safemem",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build_const"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.4.0"
|
||||
|
@ -315,6 +321,15 @@ version = "0.1.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
|
||||
dependencies = [
|
||||
"build_const",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.2.0"
|
||||
|
@ -430,6 +445,7 @@ dependencies = [
|
|||
"semver-parser 0.9.0",
|
||||
"serde",
|
||||
"sourcemap",
|
||||
"swc_bundler",
|
||||
"swc_common",
|
||||
"swc_ecmascript",
|
||||
"sys-info",
|
||||
|
@ -661,6 +677,12 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.17"
|
||||
|
@ -1475,6 +1497,16 @@ version = "2.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.8.0"
|
||||
|
@ -1638,6 +1670,12 @@ dependencies = [
|
|||
"proc-macro2 1.0.21",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "radix_fmt"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce082a9940a7ace2ad4a8b7d0b1eac6aa378895f18be598230c5f2284ac05426"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.6.5"
|
||||
|
@ -1828,6 +1866,12 @@ version = "0.6.18"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
|
||||
|
||||
[[package]]
|
||||
name = "relative-path"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65aff7c83039e88c1c0b4bedf8dfa93d6ec84d5fc2945b37c1fa4186f46c5f94"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
|
@ -2225,6 +2269,32 @@ dependencies = [
|
|||
"string_cache_codegen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_bundler"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dabc79c5bf47498e16a01134846fbb677dd9c7233c591710587d76bd30cbe02"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"crc",
|
||||
"indexmap",
|
||||
"is-macro",
|
||||
"log",
|
||||
"once_cell",
|
||||
"petgraph",
|
||||
"radix_fmt",
|
||||
"relative-path",
|
||||
"retain_mut",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_codegen",
|
||||
"swc_ecma_parser",
|
||||
"swc_ecma_transforms",
|
||||
"swc_ecma_utils",
|
||||
"swc_ecma_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_common"
|
||||
version = "0.10.4"
|
||||
|
|
|
@ -61,6 +61,7 @@ rustyline-derive = "0.3.1"
|
|||
serde = { version = "1.0.116", features = ["derive"] }
|
||||
sys-info = "0.7.0"
|
||||
sourcemap = "6.0.1"
|
||||
swc_bundler = "=0.11.3"
|
||||
swc_common = { version = "=0.10.4", features = ["sourcemap"] }
|
||||
swc_ecmascript = { version = "=0.10.1", features = ["codegen", "dep_graph", "parser", "react", "transforms", "visit"] }
|
||||
tempfile = "3.1.0"
|
||||
|
|
136
cli/ast.rs
136
cli/ast.rs
|
@ -1,13 +1,14 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::media_type::MediaType;
|
||||
use crate::tsc_config;
|
||||
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::serde_json;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
use std::result;
|
||||
use std::sync::Arc;
|
||||
use std::sync::RwLock;
|
||||
use swc_common::chain;
|
||||
|
@ -21,6 +22,7 @@ use swc_common::errors::HandlerFlags;
|
|||
use swc_common::FileName;
|
||||
use swc_common::Globals;
|
||||
use swc_common::Loc;
|
||||
use swc_common::SourceFile;
|
||||
use swc_common::SourceMap;
|
||||
use swc_common::Span;
|
||||
use swc_ecmascript::ast::Module;
|
||||
|
@ -38,13 +40,11 @@ use swc_ecmascript::parser::TsConfig;
|
|||
use swc_ecmascript::transforms::fixer;
|
||||
use swc_ecmascript::transforms::helpers;
|
||||
use swc_ecmascript::transforms::pass::Optional;
|
||||
use swc_ecmascript::transforms::proposals::decorators;
|
||||
use swc_ecmascript::transforms::proposals;
|
||||
use swc_ecmascript::transforms::react;
|
||||
use swc_ecmascript::transforms::typescript;
|
||||
use swc_ecmascript::visit::FoldWith;
|
||||
|
||||
type Result<V> = result::Result<V, AnyError>;
|
||||
|
||||
static TARGET: JscTarget = JscTarget::Es2020;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
|
@ -173,7 +173,10 @@ pub fn get_syntax(media_type: &MediaType) -> Syntax {
|
|||
|
||||
/// Options which can be adjusted when transpiling a module.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TranspileOptions {
|
||||
pub struct EmitOptions {
|
||||
/// Indicate if JavaScript is being checked/transformed as well, or if it is
|
||||
/// only TypeScript.
|
||||
pub check_js: bool,
|
||||
/// When emitting a legacy decorator, also emit experimental decorator meta
|
||||
/// data. Defaults to `false`.
|
||||
pub emit_metadata: bool,
|
||||
|
@ -190,9 +193,10 @@ pub struct TranspileOptions {
|
|||
pub transform_jsx: bool,
|
||||
}
|
||||
|
||||
impl Default for TranspileOptions {
|
||||
impl Default for EmitOptions {
|
||||
fn default() -> Self {
|
||||
TranspileOptions {
|
||||
EmitOptions {
|
||||
check_js: false,
|
||||
emit_metadata: false,
|
||||
inline_source_map: true,
|
||||
jsx_factory: "React.createElement".into(),
|
||||
|
@ -202,6 +206,21 @@ impl Default for TranspileOptions {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<tsc_config::TsConfig> for EmitOptions {
|
||||
fn from(config: tsc_config::TsConfig) -> Self {
|
||||
let options: tsc_config::EmitConfigOptions =
|
||||
serde_json::from_value(config.0).unwrap();
|
||||
EmitOptions {
|
||||
check_js: options.check_js,
|
||||
emit_metadata: options.emit_decorator_metadata,
|
||||
inline_source_map: true,
|
||||
jsx_factory: options.jsx_factory,
|
||||
jsx_fragment_factory: options.jsx_fragment_factory,
|
||||
transform_jsx: options.jsx == "react",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A logical structure to hold the value of a parsed module for further
|
||||
/// processing.
|
||||
#[derive(Clone)]
|
||||
|
@ -245,8 +264,8 @@ impl ParsedModule {
|
|||
/// The result is a tuple of the code and optional source map as strings.
|
||||
pub fn transpile(
|
||||
self,
|
||||
options: &TranspileOptions,
|
||||
) -> Result<(String, Option<String>)> {
|
||||
options: &EmitOptions,
|
||||
) -> Result<(String, Option<String>), AnyError> {
|
||||
let program = Program::Module(self.module);
|
||||
|
||||
let jsx_pass = react::react(
|
||||
|
@ -263,7 +282,7 @@ impl ParsedModule {
|
|||
);
|
||||
let mut passes = chain!(
|
||||
Optional::new(jsx_pass, options.transform_jsx),
|
||||
decorators::decorators(decorators::Config {
|
||||
proposals::decorators::decorators(proposals::decorators::Config {
|
||||
legacy: true,
|
||||
emit_metadata: options.emit_metadata
|
||||
}),
|
||||
|
@ -329,7 +348,7 @@ pub fn parse(
|
|||
specifier: &ModuleSpecifier,
|
||||
source: &str,
|
||||
media_type: &MediaType,
|
||||
) -> Result<ParsedModule> {
|
||||
) -> Result<ParsedModule, AnyError> {
|
||||
let source_map = SourceMap::default();
|
||||
let source_file = source_map.new_source_file(
|
||||
FileName::Custom(specifier.to_string()),
|
||||
|
@ -372,6 +391,95 @@ pub fn parse(
|
|||
})
|
||||
}
|
||||
|
||||
/// A low level function which transpiles a source module into an swc
|
||||
/// SourceFile.
|
||||
pub fn transpile_module(
|
||||
filename: &str,
|
||||
src: &str,
|
||||
media_type: &MediaType,
|
||||
emit_options: &EmitOptions,
|
||||
cm: Rc<SourceMap>,
|
||||
) -> Result<(Rc<SourceFile>, Module), AnyError> {
|
||||
// TODO(@kitsonk) DRY-up with ::parse()
|
||||
let error_buffer = ErrorBuffer::new();
|
||||
let handler = Handler::with_emitter_and_flags(
|
||||
Box::new(error_buffer.clone()),
|
||||
HandlerFlags {
|
||||
can_emit_warnings: true,
|
||||
dont_buffer_diagnostics: true,
|
||||
..HandlerFlags::default()
|
||||
},
|
||||
);
|
||||
let comments = SingleThreadedComments::default();
|
||||
let syntax = get_syntax(media_type);
|
||||
let source_file =
|
||||
cm.new_source_file(FileName::Custom(filename.to_string()), src.to_string());
|
||||
let lexer = Lexer::new(
|
||||
syntax,
|
||||
TARGET,
|
||||
StringInput::from(&*source_file),
|
||||
Some(&comments),
|
||||
);
|
||||
let mut parser = swc_ecmascript::parser::Parser::new_from(lexer);
|
||||
let sm = cm.clone();
|
||||
let module = parser.parse_module().map_err(move |err| {
|
||||
let mut diagnostic = err.into_diagnostic(&handler);
|
||||
diagnostic.emit();
|
||||
|
||||
DiagnosticBuffer::from_error_buffer(error_buffer, |span| {
|
||||
sm.lookup_char_pos(span.lo)
|
||||
})
|
||||
})?;
|
||||
// TODO(@kitsonk) DRY-up with ::transpile()
|
||||
let jsx_pass = react::react(
|
||||
cm,
|
||||
Some(&comments),
|
||||
react::Options {
|
||||
pragma: emit_options.jsx_factory.clone(),
|
||||
pragma_frag: emit_options.jsx_fragment_factory.clone(),
|
||||
// this will use `Object.assign()` instead of the `_extends` helper
|
||||
// when spreading props.
|
||||
use_builtins: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let mut passes = chain!(
|
||||
Optional::new(jsx_pass, emit_options.transform_jsx),
|
||||
proposals::decorators::decorators(proposals::decorators::Config {
|
||||
legacy: true,
|
||||
emit_metadata: emit_options.emit_metadata
|
||||
}),
|
||||
typescript::strip(),
|
||||
fixer(Some(&comments)),
|
||||
);
|
||||
let module = module.fold_with(&mut passes);
|
||||
|
||||
Ok((source_file, module))
|
||||
}
|
||||
|
||||
pub struct BundleHook;
|
||||
|
||||
impl swc_bundler::Hook for BundleHook {
|
||||
fn get_import_meta_url(
|
||||
&self,
|
||||
span: swc_common::Span,
|
||||
file: &swc_common::FileName,
|
||||
) -> Result<Option<swc_ecmascript::ast::Expr>, AnyError> {
|
||||
// we use custom file names, and swc "wraps" these in `<` and `>` so, we
|
||||
// want to strip those back out.
|
||||
let mut value = file.to_string();
|
||||
value.pop();
|
||||
value.remove(0);
|
||||
Ok(Some(swc_ecmascript::ast::Expr::Lit(
|
||||
swc_ecmascript::ast::Lit::Str(swc_ecmascript::ast::Str {
|
||||
span,
|
||||
value: value.into(),
|
||||
has_escape: false,
|
||||
}),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -436,7 +544,7 @@ mod tests {
|
|||
let module = parse(&specifier, source, &MediaType::TypeScript)
|
||||
.expect("could not parse module");
|
||||
let (code, maybe_map) = module
|
||||
.transpile(&TranspileOptions::default())
|
||||
.transpile(&EmitOptions::default())
|
||||
.expect("could not strip types");
|
||||
assert!(code.starts_with("var D;\n(function(D) {\n"));
|
||||
assert!(
|
||||
|
@ -460,7 +568,7 @@ mod tests {
|
|||
let module = parse(&specifier, source, &MediaType::TSX)
|
||||
.expect("could not parse module");
|
||||
let (code, _) = module
|
||||
.transpile(&TranspileOptions::default())
|
||||
.transpile(&EmitOptions::default())
|
||||
.expect("could not strip types");
|
||||
assert!(code.contains("React.createElement(\"div\", null"));
|
||||
}
|
||||
|
@ -491,7 +599,7 @@ mod tests {
|
|||
let module = parse(&specifier, source, &MediaType::TypeScript)
|
||||
.expect("could not parse module");
|
||||
let (code, _) = module
|
||||
.transpile(&TranspileOptions::default())
|
||||
.transpile(&EmitOptions::default())
|
||||
.expect("could not strip types");
|
||||
assert!(code.contains("_applyDecoratedDescriptor("));
|
||||
}
|
||||
|
|
38
cli/flags.rs
38
cli/flags.rs
|
@ -402,14 +402,7 @@ fn install_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
|||
}
|
||||
|
||||
fn bundle_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||
// TODO(nayeemrmn): Replace the next couple lines with `compile_args_parse()`
|
||||
// once `deno bundle --no-check` is supported.
|
||||
importmap_arg_parse(flags, matches);
|
||||
no_remote_arg_parse(flags, matches);
|
||||
config_arg_parse(flags, matches);
|
||||
reload_arg_parse(flags, matches);
|
||||
lock_args_parse(flags, matches);
|
||||
ca_file_arg_parse(flags, matches);
|
||||
compile_args_parse(flags, matches);
|
||||
|
||||
let source_file = matches.value_of("source_file").unwrap().to_string();
|
||||
|
||||
|
@ -776,16 +769,7 @@ These must be added to the path manually if required.")
|
|||
}
|
||||
|
||||
fn bundle_subcommand<'a, 'b>() -> App<'a, 'b> {
|
||||
SubCommand::with_name("bundle")
|
||||
// TODO(nayeemrmn): Replace the next couple lines with `compile_args()` once
|
||||
// `deno bundle --no-check` is supported.
|
||||
.arg(importmap_arg())
|
||||
.arg(no_remote_arg())
|
||||
.arg(config_arg())
|
||||
.arg(reload_arg())
|
||||
.arg(lock_arg())
|
||||
.arg(lock_write_arg())
|
||||
.arg(ca_file_arg())
|
||||
compile_args(SubCommand::with_name("bundle"))
|
||||
.arg(
|
||||
Arg::with_name("source_file")
|
||||
.takes_value(true)
|
||||
|
@ -2353,6 +2337,24 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bundle_nocheck() {
|
||||
let r =
|
||||
flags_from_vec_safe(svec!["deno", "bundle", "--no-check", "script.ts"])
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
r,
|
||||
Flags {
|
||||
subcommand: DenoSubcommand::Bundle {
|
||||
source_file: "script.ts".to_string(),
|
||||
out_file: None,
|
||||
},
|
||||
no_check: true,
|
||||
..Flags::default()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_importmap() {
|
||||
let r = flags_from_vec_safe(svec![
|
||||
|
|
37
cli/main.rs
37
cli/main.rs
|
@ -65,6 +65,7 @@ use crate::fs as deno_fs;
|
|||
use crate::media_type::MediaType;
|
||||
use crate::permissions::Permissions;
|
||||
use crate::program_state::ProgramState;
|
||||
use crate::specifier_handler::FetchHandler;
|
||||
use crate::worker::MainWorker;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::future::FutureExt;
|
||||
|
@ -304,7 +305,7 @@ async fn bundle_command(
|
|||
let module_specifier = ModuleSpecifier::resolve_url_or_path(&source_file)?;
|
||||
|
||||
debug!(">>>>> bundle START");
|
||||
let program_state = ProgramState::new(flags)?;
|
||||
let program_state = ProgramState::new(flags.clone())?;
|
||||
|
||||
info!(
|
||||
"{} {}",
|
||||
|
@ -312,10 +313,36 @@ async fn bundle_command(
|
|||
module_specifier.to_string()
|
||||
);
|
||||
|
||||
let output = program_state
|
||||
.ts_compiler
|
||||
.bundle(&program_state, module_specifier)
|
||||
.await?;
|
||||
let output = if flags.no_check {
|
||||
let handler = Rc::new(RefCell::new(FetchHandler::new(
|
||||
&program_state,
|
||||
Permissions::allow_all(),
|
||||
)?));
|
||||
let mut builder = module_graph2::GraphBuilder2::new(
|
||||
handler,
|
||||
program_state.maybe_import_map.clone(),
|
||||
);
|
||||
builder.insert(&module_specifier).await?;
|
||||
let graph = builder.get_graph(&program_state.lockfile)?;
|
||||
|
||||
let (s, stats, maybe_ignored_options) =
|
||||
graph.bundle(module_graph2::BundleOptions {
|
||||
debug: flags.log_level == Some(Level::Debug),
|
||||
maybe_config_path: flags.config_path,
|
||||
})?;
|
||||
|
||||
if let Some(ignored_options) = maybe_ignored_options {
|
||||
eprintln!("{}", ignored_options);
|
||||
}
|
||||
debug!("{}", stats);
|
||||
|
||||
s
|
||||
} else {
|
||||
program_state
|
||||
.ts_compiler
|
||||
.bundle(&program_state, module_specifier)
|
||||
.await?
|
||||
};
|
||||
|
||||
debug!(">>>>> bundle END");
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use crate::ast;
|
||||
use crate::ast::parse;
|
||||
use crate::ast::transpile_module;
|
||||
use crate::ast::BundleHook;
|
||||
use crate::ast::EmitOptions;
|
||||
use crate::ast::Location;
|
||||
use crate::ast::ParsedModule;
|
||||
use crate::import_map::ImportMap;
|
||||
|
@ -21,6 +23,7 @@ use crate::tsc_config::TsConfig;
|
|||
use crate::version;
|
||||
use crate::AnyError;
|
||||
|
||||
use deno_core::error::Context;
|
||||
use deno_core::futures::stream::FuturesUnordered;
|
||||
use deno_core::futures::stream::StreamExt;
|
||||
use deno_core::serde_json::json;
|
||||
|
@ -38,7 +41,6 @@ use std::rc::Rc;
|
|||
use std::result;
|
||||
use std::sync::Mutex;
|
||||
use std::time::Instant;
|
||||
use swc_ecmascript::dep_graph::DependencyKind;
|
||||
|
||||
lazy_static! {
|
||||
/// Matched the `@deno-types` pragma.
|
||||
|
@ -108,6 +110,59 @@ impl fmt::Display for GraphError {
|
|||
|
||||
impl Error for GraphError {}
|
||||
|
||||
/// A structure for handling bundle loading, which is implemented here, to
|
||||
/// avoid a circular dependency with `ast`.
|
||||
struct BundleLoader<'a> {
|
||||
cm: Rc<swc_common::SourceMap>,
|
||||
graph: &'a Graph2,
|
||||
emit_options: &'a EmitOptions,
|
||||
}
|
||||
|
||||
impl<'a> BundleLoader<'a> {
|
||||
pub fn new(
|
||||
graph: &'a Graph2,
|
||||
emit_options: &'a EmitOptions,
|
||||
cm: Rc<swc_common::SourceMap>,
|
||||
) -> Self {
|
||||
BundleLoader {
|
||||
cm,
|
||||
graph,
|
||||
emit_options,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl swc_bundler::Load for BundleLoader<'_> {
|
||||
fn load(
|
||||
&self,
|
||||
file: &swc_common::FileName,
|
||||
) -> Result<(Rc<swc_common::SourceFile>, swc_ecmascript::ast::Module), AnyError>
|
||||
{
|
||||
match file {
|
||||
swc_common::FileName::Custom(filename) => {
|
||||
let specifier = ModuleSpecifier::resolve_url_or_path(filename)
|
||||
.context("Failed to convert swc FileName to ModuleSpecifier.")?;
|
||||
if let Some(src) = self.graph.get_source(&specifier) {
|
||||
let media_type = self
|
||||
.graph
|
||||
.get_media_type(&specifier)
|
||||
.context("Looking up media type during bundling.")?;
|
||||
transpile_module(
|
||||
filename,
|
||||
&src,
|
||||
&media_type,
|
||||
self.emit_options,
|
||||
self.cm.clone(),
|
||||
)
|
||||
} else {
|
||||
Err(MissingDependency(specifier, "<bundle>".to_string()).into())
|
||||
}
|
||||
}
|
||||
_ => unreachable!("Received request for unsupported filename {:?}", file),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An enum which represents the parsed out values of references in source code.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
enum TypeScriptReference {
|
||||
|
@ -273,10 +328,9 @@ impl Module {
|
|||
|
||||
// Parse out all the syntactical dependencies for a module
|
||||
let dependencies = parsed_module.analyze_dependencies();
|
||||
for desc in dependencies
|
||||
.iter()
|
||||
.filter(|desc| desc.kind != DependencyKind::Require)
|
||||
{
|
||||
for desc in dependencies.iter().filter(|desc| {
|
||||
desc.kind != swc_ecmascript::dep_graph::DependencyKind::Require
|
||||
}) {
|
||||
let location = Location {
|
||||
filename: self.specifier.to_string(),
|
||||
col: desc.col,
|
||||
|
@ -301,8 +355,8 @@ impl Module {
|
|||
.dependencies
|
||||
.entry(desc.specifier.to_string())
|
||||
.or_default();
|
||||
if desc.kind == DependencyKind::ExportType
|
||||
|| desc.kind == DependencyKind::ImportType
|
||||
if desc.kind == swc_ecmascript::dep_graph::DependencyKind::ExportType
|
||||
|| desc.kind == swc_ecmascript::dep_graph::DependencyKind::ImportType
|
||||
{
|
||||
dep.maybe_type = Some(specifier);
|
||||
} else {
|
||||
|
@ -392,6 +446,12 @@ impl fmt::Display for Stats {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct BundleOptions {
|
||||
pub debug: bool,
|
||||
pub maybe_config_path: Option<String>,
|
||||
}
|
||||
|
||||
/// A structure which provides options when transpiling modules.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TranspileOptions {
|
||||
|
@ -431,6 +491,76 @@ impl Graph2 {
|
|||
}
|
||||
}
|
||||
|
||||
/// Transform the module graph into a single JavaScript module which is
|
||||
/// returned as a `String` in the result.
|
||||
pub fn bundle(
|
||||
&self,
|
||||
options: BundleOptions,
|
||||
) -> Result<(String, Stats, Option<IgnoredCompilerOptions>), AnyError> {
|
||||
if self.roots.is_empty() || self.roots.len() > 1 {
|
||||
return Err(NotSupported(format!("Bundling is only supported when there is a single root module in the graph. Found: {}", self.roots.len())).into());
|
||||
}
|
||||
|
||||
let start = Instant::now();
|
||||
let root_specifier = self.roots[0].clone();
|
||||
let mut ts_config = TsConfig::new(json!({
|
||||
"checkJs": false,
|
||||
"emitDecoratorMetadata": false,
|
||||
"jsx": "react",
|
||||
"jsxFactory": "React.createElement",
|
||||
"jsxFragmentFactory": "React.Fragment",
|
||||
}));
|
||||
let maybe_ignored_options =
|
||||
ts_config.merge_user_config(options.maybe_config_path)?;
|
||||
let emit_options: EmitOptions = ts_config.into();
|
||||
let cm = Rc::new(swc_common::SourceMap::new(
|
||||
swc_common::FilePathMapping::empty(),
|
||||
));
|
||||
let loader = BundleLoader::new(self, &emit_options, cm.clone());
|
||||
let hook = Box::new(BundleHook);
|
||||
let globals = swc_common::Globals::new();
|
||||
let bundler = swc_bundler::Bundler::new(
|
||||
&globals,
|
||||
cm.clone(),
|
||||
loader,
|
||||
self,
|
||||
swc_bundler::Config::default(),
|
||||
hook,
|
||||
);
|
||||
let mut entries = HashMap::new();
|
||||
entries.insert(
|
||||
"bundle".to_string(),
|
||||
swc_common::FileName::Custom(root_specifier.to_string()),
|
||||
);
|
||||
let output = bundler
|
||||
.bundle(entries)
|
||||
.context("Unable to output bundle during Graph2::bundle().")?;
|
||||
let mut buf = Vec::new();
|
||||
{
|
||||
let mut emitter = swc_ecmascript::codegen::Emitter {
|
||||
cfg: swc_ecmascript::codegen::Config { minify: false },
|
||||
cm: cm.clone(),
|
||||
comments: None,
|
||||
wr: Box::new(swc_ecmascript::codegen::text_writer::JsWriter::new(
|
||||
cm, "\n", &mut buf, None,
|
||||
)),
|
||||
};
|
||||
|
||||
emitter
|
||||
.emit_module(&output[0].module)
|
||||
.context("Unable to emit bundle during Graph2::bundle().")?;
|
||||
}
|
||||
|
||||
let s = String::from_utf8(buf)
|
||||
.context("Emitted bundle is an invalid utf-8 string.")?;
|
||||
let stats = Stats(vec![
|
||||
("Files".to_string(), self.modules.len() as u128),
|
||||
("Total time".to_string(), start.elapsed().as_millis()),
|
||||
]);
|
||||
|
||||
Ok((s, stats, maybe_ignored_options))
|
||||
}
|
||||
|
||||
fn contains_module(&self, specifier: &ModuleSpecifier) -> bool {
|
||||
let s = self.resolve_specifier(specifier);
|
||||
self.modules.contains_key(s)
|
||||
|
@ -725,16 +855,7 @@ impl Graph2 {
|
|||
let maybe_ignored_options =
|
||||
ts_config.merge_user_config(options.maybe_config_path)?;
|
||||
|
||||
let compiler_options = ts_config.as_transpile_config()?;
|
||||
let check_js = compiler_options.check_js;
|
||||
let transform_jsx = compiler_options.jsx == "react";
|
||||
let emit_options = ast::TranspileOptions {
|
||||
emit_metadata: compiler_options.emit_decorator_metadata,
|
||||
inline_source_map: true,
|
||||
jsx_factory: compiler_options.jsx_factory,
|
||||
jsx_fragment_factory: compiler_options.jsx_fragment_factory,
|
||||
transform_jsx,
|
||||
};
|
||||
let emit_options: EmitOptions = ts_config.clone().into();
|
||||
|
||||
let mut emit_count: u128 = 0;
|
||||
for (_, module) in self.modules.iter_mut() {
|
||||
|
@ -748,7 +869,7 @@ impl Graph2 {
|
|||
}
|
||||
// if we don't have check_js enabled, we won't touch non TypeScript
|
||||
// modules
|
||||
if !(check_js
|
||||
if !(emit_options.check_js
|
||||
|| module.media_type == MediaType::TSX
|
||||
|| module.media_type == MediaType::TypeScript)
|
||||
{
|
||||
|
@ -781,6 +902,27 @@ impl Graph2 {
|
|||
}
|
||||
}
|
||||
|
||||
impl swc_bundler::Resolve for Graph2 {
|
||||
fn resolve(
|
||||
&self,
|
||||
referrer: &swc_common::FileName,
|
||||
specifier: &str,
|
||||
) -> Result<swc_common::FileName, AnyError> {
|
||||
let referrer = if let swc_common::FileName::Custom(referrer) = referrer {
|
||||
ModuleSpecifier::resolve_url_or_path(referrer)
|
||||
.context("Cannot resolve swc FileName to a module specifier")?
|
||||
} else {
|
||||
unreachable!(
|
||||
"An unexpected referrer was passed when bundling: {:?}",
|
||||
referrer
|
||||
)
|
||||
};
|
||||
let specifier = self.resolve(specifier, &referrer)?;
|
||||
|
||||
Ok(swc_common::FileName::Custom(specifier.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
/// A structure for building a dependency graph of modules.
|
||||
pub struct GraphBuilder2 {
|
||||
fetched: HashSet<ModuleSpecifier>,
|
||||
|
@ -1094,6 +1236,50 @@ pub mod tests {
|
|||
assert_eq!(module.maybe_version, expected);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_graph_bundle() {
|
||||
let tests = vec![
|
||||
("file:///tests/fixture01.ts", "fixture01.out"),
|
||||
("file:///tests/fixture02.ts", "fixture02.out"),
|
||||
("file:///tests/fixture03.ts", "fixture03.out"),
|
||||
("file:///tests/fixture04.ts", "fixture04.out"),
|
||||
("file:///tests/fixture05.ts", "fixture05.out"),
|
||||
("file:///tests/fixture06.ts", "fixture06.out"),
|
||||
("file:///tests/fixture07.ts", "fixture07.out"),
|
||||
("file:///tests/fixture08.ts", "fixture08.out"),
|
||||
("file:///tests/fixture09.ts", "fixture09.out"),
|
||||
("file:///tests/fixture10.ts", "fixture10.out"),
|
||||
("file:///tests/fixture11.ts", "fixture11.out"),
|
||||
("file:///tests/fixture12.ts", "fixture12.out"),
|
||||
("file:///tests/fixture13.ts", "fixture13.out"),
|
||||
("file:///tests/fixture14.ts", "fixture14.out"),
|
||||
];
|
||||
let c = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
|
||||
let fixtures = c.join("tests/bundle");
|
||||
|
||||
for (specifier, expected_str) in tests {
|
||||
let specifier = ModuleSpecifier::resolve_url_or_path(specifier).unwrap();
|
||||
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
|
||||
fixtures: fixtures.clone(),
|
||||
..MockSpecifierHandler::default()
|
||||
}));
|
||||
let mut builder = GraphBuilder2::new(handler.clone(), None);
|
||||
builder
|
||||
.insert(&specifier)
|
||||
.await
|
||||
.expect("module not inserted");
|
||||
let graph = builder.get_graph(&None).expect("could not get graph");
|
||||
let (actual, stats, maybe_ignored_options) = graph
|
||||
.bundle(BundleOptions::default())
|
||||
.expect("could not bundle");
|
||||
assert_eq!(stats.0.len(), 2);
|
||||
assert_eq!(maybe_ignored_options, None);
|
||||
let expected_path = fixtures.join(expected_str);
|
||||
let expected = fs::read_to_string(expected_path).unwrap();
|
||||
assert_eq!(actual, expected, "fixture: {}", specifier);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_graph_info() {
|
||||
let c = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
|
||||
|
|
3
cli/tests/bundle/file_tests-fixture01.ts
Normal file
3
cli/tests/bundle/file_tests-fixture01.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import * as a from "./subdir/a.ts";
|
||||
|
||||
console.log(a);
|
4
cli/tests/bundle/file_tests-fixture02.ts
Normal file
4
cli/tests/bundle/file_tests-fixture02.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
import * as b from "./subdir/b.ts";
|
||||
|
||||
console.log(b.b); // "b"
|
||||
console.log(b.c); // { c: "c", default: class C }
|
3
cli/tests/bundle/file_tests-fixture03.ts
Normal file
3
cli/tests/bundle/file_tests-fixture03.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import { d } from "./subdir/d.ts";
|
||||
|
||||
console.log(d);
|
3
cli/tests/bundle/file_tests-fixture04.ts
Normal file
3
cli/tests/bundle/file_tests-fixture04.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
const a = await import("./subdir/a.ts");
|
||||
|
||||
console.log(a);
|
3
cli/tests/bundle/file_tests-fixture05.ts
Normal file
3
cli/tests/bundle/file_tests-fixture05.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import { a } from "./subdir/e.ts";
|
||||
|
||||
console.log(a);
|
4
cli/tests/bundle/file_tests-fixture06.ts
Normal file
4
cli/tests/bundle/file_tests-fixture06.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
import { isMain, modUrl } from "./subdir/f.ts";
|
||||
|
||||
console.log(isMain, modUrl);
|
||||
console.log(import.meta.main, import.meta.url);
|
4
cli/tests/bundle/file_tests-fixture07.ts
Normal file
4
cli/tests/bundle/file_tests-fixture07.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
import { G } from "./subdir/g.ts";
|
||||
import { H } from "./subdir/h.ts";
|
||||
|
||||
console.log(new G(true), new H(true));
|
1
cli/tests/bundle/file_tests-fixture08.ts
Normal file
1
cli/tests/bundle/file_tests-fixture08.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * as a from "./subdir/a.ts";
|
1
cli/tests/bundle/file_tests-fixture09.ts
Normal file
1
cli/tests/bundle/file_tests-fixture09.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export { a } from "./subdir/k.ts";
|
7
cli/tests/bundle/file_tests-fixture10.ts
Normal file
7
cli/tests/bundle/file_tests-fixture10.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { a as defaultA } from "./subdir/l.ts";
|
||||
|
||||
const o: { a?: string } = {};
|
||||
|
||||
const { a = defaultA } = o;
|
||||
|
||||
console.log(a);
|
32
cli/tests/bundle/file_tests-fixture11.ts
Normal file
32
cli/tests/bundle/file_tests-fixture11.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { a as defaultA, O } from "./subdir/m.ts";
|
||||
export { O } from "./subdir/m.ts";
|
||||
|
||||
interface AOptions {
|
||||
a?(): void;
|
||||
c?: O;
|
||||
}
|
||||
|
||||
class A {
|
||||
#a: () => void;
|
||||
#c?: O;
|
||||
constructor(o: AOptions = {}) {
|
||||
const {
|
||||
a = defaultA,
|
||||
c,
|
||||
} = o;
|
||||
this.#a = a;
|
||||
this.#c = c;
|
||||
}
|
||||
|
||||
a() {
|
||||
this.#a();
|
||||
}
|
||||
|
||||
c() {
|
||||
console.log(this.#c);
|
||||
}
|
||||
}
|
||||
|
||||
const a = new A();
|
||||
a.a();
|
||||
a.c();
|
7
cli/tests/bundle/file_tests-fixture12.ts
Normal file
7
cli/tests/bundle/file_tests-fixture12.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { a } from "./subdir/p.ts";
|
||||
|
||||
function b() {
|
||||
a();
|
||||
}
|
||||
|
||||
b();
|
11
cli/tests/bundle/file_tests-fixture13.ts
Normal file
11
cli/tests/bundle/file_tests-fixture13.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { D, d } from "./subdir/q.ts";
|
||||
|
||||
class A {
|
||||
private s: D = d();
|
||||
|
||||
a() {
|
||||
this.s.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
new A();
|
4
cli/tests/bundle/file_tests-fixture14.ts
Normal file
4
cli/tests/bundle/file_tests-fixture14.ts
Normal file
|
@ -0,0 +1,4 @@
|
|||
// @deno-types="https://deno.land/x/lib/mod.d.ts"
|
||||
import * as lib from "https://deno.land/x/lib/mod.js";
|
||||
|
||||
console.log(lib);
|
1
cli/tests/bundle/file_tests-subdir-a.ts
Normal file
1
cli/tests/bundle/file_tests-subdir-a.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export const a = "a";
|
3
cli/tests/bundle/file_tests-subdir-b.ts
Normal file
3
cli/tests/bundle/file_tests-subdir-b.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export * as c from "./c.ts";
|
||||
|
||||
export const b = "b";
|
2
cli/tests/bundle/file_tests-subdir-c.ts
Normal file
2
cli/tests/bundle/file_tests-subdir-c.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export const c = "c";
|
||||
export default class C {}
|
3
cli/tests/bundle/file_tests-subdir-d.ts
Normal file
3
cli/tests/bundle/file_tests-subdir-d.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
import { a } from "./a.ts";
|
||||
|
||||
export const d = { a };
|
1
cli/tests/bundle/file_tests-subdir-e.ts
Normal file
1
cli/tests/bundle/file_tests-subdir-e.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from "./a.ts";
|
2
cli/tests/bundle/file_tests-subdir-f.ts
Normal file
2
cli/tests/bundle/file_tests-subdir-f.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export const isMain = import.meta.main;
|
||||
export const modUrl = import.meta.url;
|
12
cli/tests/bundle/file_tests-subdir-g.ts
Normal file
12
cli/tests/bundle/file_tests-subdir-g.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
const g: number[] = [];
|
||||
|
||||
export class G {
|
||||
#g!: number[];
|
||||
constructor(shared: boolean) {
|
||||
if (shared) {
|
||||
this.#g = g;
|
||||
} else {
|
||||
this.#g = [];
|
||||
}
|
||||
}
|
||||
}
|
12
cli/tests/bundle/file_tests-subdir-h.ts
Normal file
12
cli/tests/bundle/file_tests-subdir-h.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
const g: number[] = [];
|
||||
|
||||
export class H {
|
||||
#g!: number[];
|
||||
constructor(shared: boolean) {
|
||||
if (shared) {
|
||||
this.#g = g;
|
||||
} else {
|
||||
this.#g = [];
|
||||
}
|
||||
}
|
||||
}
|
3
cli/tests/bundle/file_tests-subdir-i.ts
Normal file
3
cli/tests/bundle/file_tests-subdir-i.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export function a(...d: string[]): string {
|
||||
return d.join(" ");
|
||||
}
|
3
cli/tests/bundle/file_tests-subdir-j.ts
Normal file
3
cli/tests/bundle/file_tests-subdir-j.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export function a(...d: string[]): string {
|
||||
return d.join("/");
|
||||
}
|
11
cli/tests/bundle/file_tests-subdir-k.ts
Normal file
11
cli/tests/bundle/file_tests-subdir-k.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
import * as _i from "./i.ts";
|
||||
import * as _j from "./j.ts";
|
||||
|
||||
const k = globalThis.value ? _i : _j;
|
||||
|
||||
export const i = _i;
|
||||
export const j = _j;
|
||||
|
||||
export const {
|
||||
a,
|
||||
} = k;
|
1
cli/tests/bundle/file_tests-subdir-l.ts
Normal file
1
cli/tests/bundle/file_tests-subdir-l.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export { a } from "./a.ts";
|
2
cli/tests/bundle/file_tests-subdir-m.ts
Normal file
2
cli/tests/bundle/file_tests-subdir-m.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { a } from "./n.ts";
|
||||
export { O } from "./o.ts";
|
3
cli/tests/bundle/file_tests-subdir-n.ts
Normal file
3
cli/tests/bundle/file_tests-subdir-n.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export function a() {
|
||||
console.log("a");
|
||||
}
|
5
cli/tests/bundle/file_tests-subdir-o.ts
Normal file
5
cli/tests/bundle/file_tests-subdir-o.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
export enum O {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
}
|
1
cli/tests/bundle/file_tests-subdir-p.ts
Normal file
1
cli/tests/bundle/file_tests-subdir-p.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from "./i.ts";
|
13
cli/tests/bundle/file_tests-subdir-q.ts
Normal file
13
cli/tests/bundle/file_tests-subdir-q.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
/* eslint-disable */
|
||||
export interface D {
|
||||
resolve: any;
|
||||
reject: any;
|
||||
}
|
||||
|
||||
export function d(): D {
|
||||
let methods;
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
methods = { resolve, reject };
|
||||
});
|
||||
return Object.assign(promise, methods);
|
||||
}
|
7
cli/tests/bundle/fixture01.out
Normal file
7
cli/tests/bundle/fixture01.out
Normal file
|
@ -0,0 +1,7 @@
|
|||
const a = function() {
|
||||
const a = "a";
|
||||
return {
|
||||
a
|
||||
};
|
||||
}();
|
||||
console.log(a);
|
11
cli/tests/bundle/fixture02.out
Normal file
11
cli/tests/bundle/fixture02.out
Normal file
|
@ -0,0 +1,11 @@
|
|||
const c = function() {
|
||||
const c1 = "c";
|
||||
class C {
|
||||
}
|
||||
return {
|
||||
c: c1,
|
||||
default: C
|
||||
};
|
||||
}();
|
||||
console.log("b");
|
||||
console.log(c);
|
4
cli/tests/bundle/fixture03.out
Normal file
4
cli/tests/bundle/fixture03.out
Normal file
|
@ -0,0 +1,4 @@
|
|||
const d = {
|
||||
a: "a"
|
||||
};
|
||||
console.log(d);
|
2
cli/tests/bundle/fixture04.out
Normal file
2
cli/tests/bundle/fixture04.out
Normal file
|
@ -0,0 +1,2 @@
|
|||
const a = await import("./subdir/a.ts");
|
||||
console.log(a);
|
1
cli/tests/bundle/fixture05.out
Normal file
1
cli/tests/bundle/fixture05.out
Normal file
|
@ -0,0 +1 @@
|
|||
console.log("a");
|
2
cli/tests/bundle/fixture06.out
Normal file
2
cli/tests/bundle/fixture06.out
Normal file
|
@ -0,0 +1,2 @@
|
|||
console.log(false, "file:///tests/subdir/f.ts");
|
||||
console.log(import.meta.main, "file:///tests/fixture06.ts");
|
23
cli/tests/bundle/fixture07.out
Normal file
23
cli/tests/bundle/fixture07.out
Normal file
|
@ -0,0 +1,23 @@
|
|||
const g = [];
|
||||
class G {
|
||||
#g;
|
||||
constructor(shared){
|
||||
if (shared) {
|
||||
this.#g = g;
|
||||
} else {
|
||||
this.#g = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
const g1 = [];
|
||||
class H {
|
||||
#g;
|
||||
constructor(shared1){
|
||||
if (shared1) {
|
||||
this.#g = g1;
|
||||
} else {
|
||||
this.#g = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(new G(true), new H(true));
|
7
cli/tests/bundle/fixture08.out
Normal file
7
cli/tests/bundle/fixture08.out
Normal file
|
@ -0,0 +1,7 @@
|
|||
const a = function() {
|
||||
const a1 = "a";
|
||||
return {
|
||||
a: a1
|
||||
};
|
||||
}();
|
||||
export { a };
|
19
cli/tests/bundle/fixture09.out
Normal file
19
cli/tests/bundle/fixture09.out
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 };
|
4
cli/tests/bundle/fixture10.out
Normal file
4
cli/tests/bundle/fixture10.out
Normal file
|
@ -0,0 +1,4 @@
|
|||
const o = {
|
||||
};
|
||||
const { a ="a" } = o;
|
||||
console.log(a);
|
31
cli/tests/bundle/fixture11.out
Normal file
31
cli/tests/bundle/fixture11.out
Normal file
|
@ -0,0 +1,31 @@
|
|||
function a() {
|
||||
console.log("a");
|
||||
}
|
||||
var O;
|
||||
(function(O1) {
|
||||
O1[O1["A"] = 0] = "A";
|
||||
O1[O1["B"] = 1] = "B";
|
||||
O1[O1["C"] = 2] = "C";
|
||||
})((void 0) || (O = {
|
||||
}));
|
||||
const O1 = void 0;
|
||||
export { O1 as O };
|
||||
class A {
|
||||
#a;
|
||||
#c;
|
||||
constructor(o = {
|
||||
}){
|
||||
const { a: a1 = a , c , } = o;
|
||||
this.#a = a1;
|
||||
this.#c = c;
|
||||
}
|
||||
a() {
|
||||
this.#a();
|
||||
}
|
||||
c() {
|
||||
console.log(this.#c);
|
||||
}
|
||||
}
|
||||
const a2 = new A();
|
||||
a2.a();
|
||||
a2.c();
|
7
cli/tests/bundle/fixture12.out
Normal file
7
cli/tests/bundle/fixture12.out
Normal file
|
@ -0,0 +1,7 @@
|
|||
function a(...d) {
|
||||
return d.join(" ");
|
||||
}
|
||||
function b() {
|
||||
a();
|
||||
}
|
||||
b();
|
17
cli/tests/bundle/fixture13.out
Normal file
17
cli/tests/bundle/fixture13.out
Normal file
|
@ -0,0 +1,17 @@
|
|||
function d() {
|
||||
let methods;
|
||||
const promise = new Promise((resolve, reject)=>{
|
||||
methods = {
|
||||
resolve,
|
||||
reject
|
||||
};
|
||||
});
|
||||
return Object.assign(promise, methods);
|
||||
}
|
||||
class A {
|
||||
s = d();
|
||||
a() {
|
||||
this.s.resolve();
|
||||
}
|
||||
}
|
||||
new A();
|
25
cli/tests/bundle/fixture14.out
Normal file
25
cli/tests/bundle/fixture14.out
Normal file
|
@ -0,0 +1,25 @@
|
|||
const lib = function() {
|
||||
const a = function() {
|
||||
const a1 = [];
|
||||
return {
|
||||
a: a1
|
||||
};
|
||||
}();
|
||||
const b = function() {
|
||||
const b1 = [];
|
||||
return {
|
||||
b: b1
|
||||
};
|
||||
}();
|
||||
const c = function() {
|
||||
const c1;
|
||||
return {
|
||||
c: c1
|
||||
};
|
||||
}();
|
||||
const mod;
|
||||
return {
|
||||
mod
|
||||
};
|
||||
}();
|
||||
console.log(lib);
|
1
cli/tests/bundle/https_deno.land-x-lib-a.ts
Normal file
1
cli/tests/bundle/https_deno.land-x-lib-a.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export const a: string[] = [];
|
1
cli/tests/bundle/https_deno.land-x-lib-b.js
Normal file
1
cli/tests/bundle/https_deno.land-x-lib-b.js
Normal file
|
@ -0,0 +1 @@
|
|||
export const b = [];
|
1
cli/tests/bundle/https_deno.land-x-lib-c.d.ts
vendored
Normal file
1
cli/tests/bundle/https_deno.land-x-lib-c.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
export const c: string[];
|
3
cli/tests/bundle/https_deno.land-x-lib-c.js
Normal file
3
cli/tests/bundle/https_deno.land-x-lib-c.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
/// <reference types="./c.d.ts" />
|
||||
|
||||
export const c = [];
|
9
cli/tests/bundle/https_deno.land-x-lib-mod.d.ts
vendored
Normal file
9
cli/tests/bundle/https_deno.land-x-lib-mod.d.ts
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
export * as a from "./a.ts";
|
||||
export * as b from "./b.js";
|
||||
export * as c from "./c.js";
|
||||
|
||||
export interface A {
|
||||
a: string;
|
||||
}
|
||||
|
||||
export const mod: A[];
|
5
cli/tests/bundle/https_deno.land-x-lib-mod.js
Normal file
5
cli/tests/bundle/https_deno.land-x-lib-mod.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
export * as a from "./a.ts";
|
||||
export * as b from "./b.js";
|
||||
export * as c from "./c.js";
|
||||
|
||||
export const mod = [];
|
|
@ -838,6 +838,49 @@ fn bundle_exports() {
|
|||
assert_eq!(output.stderr, b"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bundle_exports_no_check() {
|
||||
// First we have to generate a bundle of some module that has exports.
|
||||
let mod1 = util::root_path().join("cli/tests/subdir/mod1.ts");
|
||||
assert!(mod1.is_file());
|
||||
let t = TempDir::new().expect("tempdir fail");
|
||||
let bundle = t.path().join("mod1.bundle.js");
|
||||
let mut deno = util::deno_cmd()
|
||||
.current_dir(util::root_path())
|
||||
.arg("bundle")
|
||||
.arg("--no-check")
|
||||
.arg(mod1)
|
||||
.arg(&bundle)
|
||||
.spawn()
|
||||
.expect("failed to spawn script");
|
||||
let status = deno.wait().expect("failed to wait for the child process");
|
||||
assert!(status.success());
|
||||
assert!(bundle.is_file());
|
||||
|
||||
// Now we try to use that bundle from another module.
|
||||
let test = t.path().join("test.js");
|
||||
std::fs::write(
|
||||
&test,
|
||||
"
|
||||
import { printHello3 } from \"./mod1.bundle.js\";
|
||||
printHello3(); ",
|
||||
)
|
||||
.expect("error writing file");
|
||||
|
||||
let output = util::deno_cmd()
|
||||
.current_dir(util::root_path())
|
||||
.arg("run")
|
||||
.arg(&test)
|
||||
.output()
|
||||
.expect("failed to spawn script");
|
||||
// check the output of the test.ts program.
|
||||
assert!(std::str::from_utf8(&output.stdout)
|
||||
.unwrap()
|
||||
.trim()
|
||||
.ends_with("Hello"));
|
||||
assert_eq!(output.stderr, b"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bundle_circular() {
|
||||
// First we have to generate a bundle of some module that has exports.
|
||||
|
@ -1051,6 +1094,52 @@ fn bundle_import_map() {
|
|||
assert_eq!(output.stderr, b"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bundle_import_map_no_check() {
|
||||
let import = util::root_path().join("cli/tests/bundle_im.ts");
|
||||
let import_map_path = util::root_path().join("cli/tests/bundle_im.json");
|
||||
assert!(import.is_file());
|
||||
let t = TempDir::new().expect("tempdir fail");
|
||||
let bundle = t.path().join("import_map.bundle.js");
|
||||
let mut deno = util::deno_cmd()
|
||||
.current_dir(util::root_path())
|
||||
.arg("bundle")
|
||||
.arg("--no-check")
|
||||
.arg("--importmap")
|
||||
.arg(import_map_path)
|
||||
.arg("--unstable")
|
||||
.arg(import)
|
||||
.arg(&bundle)
|
||||
.spawn()
|
||||
.expect("failed to spawn script");
|
||||
let status = deno.wait().expect("failed to wait for the child process");
|
||||
assert!(status.success());
|
||||
assert!(bundle.is_file());
|
||||
|
||||
// Now we try to use that bundle from another module.
|
||||
let test = t.path().join("test.js");
|
||||
std::fs::write(
|
||||
&test,
|
||||
"
|
||||
import { printHello3 } from \"./import_map.bundle.js\";
|
||||
printHello3(); ",
|
||||
)
|
||||
.expect("error writing file");
|
||||
|
||||
let output = util::deno_cmd()
|
||||
.current_dir(util::root_path())
|
||||
.arg("run")
|
||||
.arg(&test)
|
||||
.output()
|
||||
.expect("failed to spawn script");
|
||||
// check the output of the test.ts program.
|
||||
assert!(std::str::from_utf8(&output.stdout)
|
||||
.unwrap()
|
||||
.trim()
|
||||
.ends_with("Hello"));
|
||||
assert_eq!(output.stderr, b"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn info_with_compiled_source() {
|
||||
let _g = util::http_server();
|
||||
|
|
|
@ -17,7 +17,7 @@ use std::str::FromStr;
|
|||
/// file, that we want to deserialize out of the final config for a transpile.
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TranspileConfigOptions {
|
||||
pub struct EmitConfigOptions {
|
||||
pub check_js: bool,
|
||||
pub emit_decorator_metadata: bool,
|
||||
pub jsx: String,
|
||||
|
@ -202,7 +202,7 @@ pub fn parse_config(
|
|||
|
||||
/// A structure for managing the configuration of TypeScript
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TsConfig(Value);
|
||||
pub struct TsConfig(pub Value);
|
||||
|
||||
impl TsConfig {
|
||||
/// Create a new `TsConfig` with the base being the `value` supplied.
|
||||
|
@ -247,15 +247,6 @@ impl TsConfig {
|
|||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the current configuration as a `TranspileConfigOptions` structure.
|
||||
pub fn as_transpile_config(
|
||||
&self,
|
||||
) -> Result<TranspileConfigOptions, AnyError> {
|
||||
let options: TranspileConfigOptions =
|
||||
serde_json::from_value(self.0.clone())?;
|
||||
Ok(options)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for TsConfig {
|
||||
|
|
Loading…
Reference in a new issue