@tishlang/tish 2.9.0 → 2.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/tish +0 -0
- package/crates/tish/Cargo.toml +2 -1
- package/crates/tish/src/cli_help.rs +47 -0
- package/crates/tish/src/main.rs +92 -6
- package/crates/tish/tests/integration_test.rs +177 -0
- package/crates/tish_compile/src/codegen.rs +255 -0
- package/crates/tish_compile/tests/perf_codegen_169_173.rs +139 -0
- package/crates/tish_compile_js/src/codegen.rs +161 -3
- package/crates/tish_compile_js/src/lib.rs +7 -3
- package/crates/tish_compile_js/src/tests_jsx.rs +341 -4
- package/crates/tish_ui/src/jsx.rs +250 -0
- package/package.json +1 -1
- package/platform/darwin-arm64/tish +0 -0
- package/platform/darwin-x64/tish +0 -0
- package/platform/linux-arm64/tish +0 -0
- package/platform/linux-x64/tish +0 -0
- package/platform/win32-x64/tish.exe +0 -0
package/bin/tish
CHANGED
|
Binary file
|
package/crates/tish/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "tishlang"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.12.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "Tish CLI - run, REPL, compile to native"
|
|
6
6
|
license-file = { workspace = true }
|
|
@@ -59,6 +59,7 @@ tishlang_runtime = { path = "../tish_runtime", version = ">=0.1" }
|
|
|
59
59
|
tishlang_core = { path = "../tish_core", version = ">=0.1" }
|
|
60
60
|
tishlang_js_to_tish = { path = "../js_to_tish", version = ">=0.1" }
|
|
61
61
|
clap = { version = "4.6.0", features = ["derive", "color"] }
|
|
62
|
+
serde_json = "1"
|
|
62
63
|
tishlang_pg = { path = "../tish_pg", version = ">=0.1", optional = true }
|
|
63
64
|
mimalloc = { version = "0.1", optional = true }
|
|
64
65
|
|
|
@@ -563,6 +563,14 @@ pub(crate) struct BuildArgs {
|
|
|
563
563
|
/// For `--target js`: `bundle` (default) merges all modules into one file; `esm` emits one `.js` per `.tish` module with real `import`/`export` (so `-o` is a directory) for Vite/Rollup tree-shaking.
|
|
564
564
|
#[arg(long, default_value = "bundle", value_name = "FORMAT", help_heading = "Options")]
|
|
565
565
|
pub format: String,
|
|
566
|
+
/// For `--target js --format esm`: package the JSX runtime (`h`/`Fragment`) is auto-imported from when a module uses JSX without importing them (default `lattish`).
|
|
567
|
+
#[arg(
|
|
568
|
+
long = "jsx-import-source",
|
|
569
|
+
default_value = "lattish",
|
|
570
|
+
value_name = "PKG",
|
|
571
|
+
help_heading = "Options"
|
|
572
|
+
)]
|
|
573
|
+
pub jsx_import_source: String,
|
|
566
574
|
/// Run the gradual type checker: `warn` prints `line:col` type diagnostics; `error` also fails the build on them. (Equivalent to setting `TISH_CHECK`.)
|
|
567
575
|
#[arg(long, value_name = "MODE", help_heading = "Options")]
|
|
568
576
|
pub check: Option<String>,
|
|
@@ -571,6 +579,42 @@ pub(crate) struct BuildArgs {
|
|
|
571
579
|
pub file: String,
|
|
572
580
|
}
|
|
573
581
|
|
|
582
|
+
#[derive(Parser)]
|
|
583
|
+
pub(crate) struct CompileModuleArgs {
|
|
584
|
+
/// `--target js` only (the single-module ESM path is JS-specific).
|
|
585
|
+
#[arg(long, default_value = "js", value_name = "TARGET", help_heading = "Options")]
|
|
586
|
+
pub target: String,
|
|
587
|
+
/// `--format esm` only (one ES module per file).
|
|
588
|
+
#[arg(long, default_value = "esm", value_name = "FORMAT", help_heading = "Options")]
|
|
589
|
+
pub format: String,
|
|
590
|
+
/// Keep relative `.tish` specifiers and bare packages verbatim so Vite's resolveId/load re-enters the plugin per module (in-graph HMR). Omit for disk-style `.tish`->`.js` rewriting.
|
|
591
|
+
#[arg(long, help_heading = "Options")]
|
|
592
|
+
pub vite_dev: bool,
|
|
593
|
+
/// Emit a v3 source map back to the `.tish` source as a `{ "js", "map" }` JSON envelope on stdout (on by default; implies no optimization).
|
|
594
|
+
#[arg(long, help_heading = "Options")]
|
|
595
|
+
pub source_map: bool,
|
|
596
|
+
/// Disable the source map; print raw ES module JS to stdout instead of the JSON envelope.
|
|
597
|
+
#[arg(long = "no-source-map", help_heading = "Options")]
|
|
598
|
+
pub no_source_map: bool,
|
|
599
|
+
/// Project root for resolving bare specifiers / `node_modules` (defaults to the file's parent).
|
|
600
|
+
#[arg(long, value_name = "DIR", help_heading = "Options")]
|
|
601
|
+
pub project_root: Option<String>,
|
|
602
|
+
/// Disable AST optimizations (forced on when a source map is emitted).
|
|
603
|
+
#[arg(long, help_heading = "Options")]
|
|
604
|
+
pub no_optimize: bool,
|
|
605
|
+
/// Package the JSX runtime (`h`/`Fragment`) is auto-imported from when a module uses JSX without importing them (default `lattish`).
|
|
606
|
+
#[arg(
|
|
607
|
+
long = "jsx-import-source",
|
|
608
|
+
default_value = "lattish",
|
|
609
|
+
value_name = "PKG",
|
|
610
|
+
help_heading = "Options"
|
|
611
|
+
)]
|
|
612
|
+
pub jsx_import_source: String,
|
|
613
|
+
/// Entry `.tish` file to compile (only this file is read; dependencies are left to the bundler).
|
|
614
|
+
#[arg(required = true, value_name = "FILE", help_heading = "Arguments")]
|
|
615
|
+
pub file: String,
|
|
616
|
+
}
|
|
617
|
+
|
|
574
618
|
#[derive(Subcommand)]
|
|
575
619
|
pub(crate) enum Commands {
|
|
576
620
|
/// Run a Tish file (interpret)
|
|
@@ -579,6 +623,9 @@ pub(crate) enum Commands {
|
|
|
579
623
|
Repl(ReplArgs),
|
|
580
624
|
/// Build native binary, wasm, wasi, or JavaScript output
|
|
581
625
|
Build(BuildArgs),
|
|
626
|
+
/// Compile a single `.tish` module to one ES module (for Vite dev / HMR); prints to stdout
|
|
627
|
+
#[command(name = "compile-module")]
|
|
628
|
+
CompileModule(CompileModuleArgs),
|
|
582
629
|
/// Parse and dump AST
|
|
583
630
|
#[command(name = "dump-ast")]
|
|
584
631
|
DumpAst {
|
package/crates/tish/src/main.rs
CHANGED
|
@@ -22,7 +22,7 @@ use tishlang_core::VmRef;
|
|
|
22
22
|
use clap::FromArgMatches;
|
|
23
23
|
use rustyline::{Behavior, ColorMode, CompletionType, Config, Editor};
|
|
24
24
|
|
|
25
|
-
use cli_help::{Cli, Commands};
|
|
25
|
+
use cli_help::{Cli, Commands, CompileModuleArgs};
|
|
26
26
|
|
|
27
27
|
/// Normalize `--feature` / `--feature http,timers,fs` / `--feature full` for VM runs and native builds.
|
|
28
28
|
fn normalize_capability_flags(features: &[String]) -> HashSet<String> {
|
|
@@ -73,7 +73,7 @@ fn native_build_features_from_cli(cli_features: &[String]) -> Vec<String> {
|
|
|
73
73
|
fn argv_with_implicit_run(mut argv: Vec<String>) -> Vec<String> {
|
|
74
74
|
if argv.len() >= 2 {
|
|
75
75
|
let first = argv[1].as_str();
|
|
76
|
-
const SUBCOMMANDS: &[&str] = &["run", "repl", "build", "dump-ast"];
|
|
76
|
+
const SUBCOMMANDS: &[&str] = &["run", "repl", "build", "compile-module", "dump-ast"];
|
|
77
77
|
let looks_like_file = !first.starts_with('-') && !SUBCOMMANDS.contains(&first);
|
|
78
78
|
if looks_like_file {
|
|
79
79
|
argv.insert(1, "run".to_string());
|
|
@@ -137,8 +137,10 @@ fn main() {
|
|
|
137
137
|
a.ios_triple.as_deref(),
|
|
138
138
|
&a.crate_type,
|
|
139
139
|
&a.format,
|
|
140
|
+
&a.jsx_import_source,
|
|
140
141
|
)
|
|
141
142
|
}
|
|
143
|
+
Some(Commands::CompileModule(a)) => compile_module(&a),
|
|
142
144
|
Some(Commands::DumpAst {
|
|
143
145
|
file,
|
|
144
146
|
ignore_indent,
|
|
@@ -543,6 +545,7 @@ fn compile_to_js(
|
|
|
543
545
|
optimize: bool,
|
|
544
546
|
source_map: bool,
|
|
545
547
|
format: &str,
|
|
548
|
+
jsx_import_source: &str,
|
|
546
549
|
) -> Result<(), String> {
|
|
547
550
|
if format != "bundle" && format != "esm" {
|
|
548
551
|
return Err(format!(
|
|
@@ -573,7 +576,14 @@ fn compile_to_js(
|
|
|
573
576
|
}
|
|
574
577
|
});
|
|
575
578
|
if format == "esm" {
|
|
576
|
-
return compile_to_js_esm(
|
|
579
|
+
return compile_to_js_esm(
|
|
580
|
+
input_path,
|
|
581
|
+
output_path,
|
|
582
|
+
optimize,
|
|
583
|
+
source_map,
|
|
584
|
+
project_root,
|
|
585
|
+
jsx_import_source,
|
|
586
|
+
);
|
|
577
587
|
}
|
|
578
588
|
let out_path = Path::new(output_path);
|
|
579
589
|
let out_path = if out_path.extension().is_none()
|
|
@@ -655,6 +665,7 @@ fn compile_to_js_esm(
|
|
|
655
665
|
optimize: bool,
|
|
656
666
|
source_map: bool,
|
|
657
667
|
project_root: Option<&Path>,
|
|
668
|
+
jsx_import_source: &str,
|
|
658
669
|
) -> Result<(), String> {
|
|
659
670
|
if source_map {
|
|
660
671
|
return Err(
|
|
@@ -670,8 +681,9 @@ fn compile_to_js_esm(
|
|
|
670
681
|
.into(),
|
|
671
682
|
);
|
|
672
683
|
}
|
|
673
|
-
let modules =
|
|
674
|
-
|
|
684
|
+
let modules =
|
|
685
|
+
tishlang_compile_js::compile_project_esm(input_path, project_root, optimize, jsx_import_source)
|
|
686
|
+
.map_err(|e| format!("{}", e))?;
|
|
675
687
|
let out_dir = Path::new(output_path);
|
|
676
688
|
fs::create_dir_all(out_dir)
|
|
677
689
|
.map_err(|e| format!("Cannot create output directory {}: {}", out_dir.display(), e))?;
|
|
@@ -703,6 +715,72 @@ fn compile_to_js_esm(
|
|
|
703
715
|
Ok(())
|
|
704
716
|
}
|
|
705
717
|
|
|
718
|
+
/// `tish compile-module FILE` (#284): compile a single `.tish` file to one ES module and print it
|
|
719
|
+
/// to stdout. This is the fast, in-graph path the Vite plugin shells out to in `load()` — only the
|
|
720
|
+
/// one file is read (no dependency graph resolution), so Vite owns the module graph and can HMR a
|
|
721
|
+
/// leaf module without a full reload.
|
|
722
|
+
///
|
|
723
|
+
/// With a source map (default), stdout is a JSON envelope `{"js":…,"map":…}` so the plugin gets
|
|
724
|
+
/// both artifacts from one spawn; with `--no-source-map`, stdout is raw ES module JS.
|
|
725
|
+
fn compile_module(args: &CompileModuleArgs) -> Result<(), String> {
|
|
726
|
+
if args.target != "js" {
|
|
727
|
+
return Err(format!(
|
|
728
|
+
"tish compile-module only supports --target js (got '{}').",
|
|
729
|
+
args.target
|
|
730
|
+
));
|
|
731
|
+
}
|
|
732
|
+
if args.format != "esm" {
|
|
733
|
+
return Err(format!(
|
|
734
|
+
"tish compile-module only supports --format esm (got '{}').",
|
|
735
|
+
args.format
|
|
736
|
+
));
|
|
737
|
+
}
|
|
738
|
+
let input_path = Path::new(&args.file)
|
|
739
|
+
.canonicalize()
|
|
740
|
+
.map_err(|e| format!("Cannot resolve {}: {}", args.file, e))?;
|
|
741
|
+
if input_path.extension().map(|e| e != "tish").unwrap_or(true) {
|
|
742
|
+
return Err(format!(
|
|
743
|
+
"tish compile-module expects a .tish file (got '{}').",
|
|
744
|
+
args.file
|
|
745
|
+
));
|
|
746
|
+
}
|
|
747
|
+
let want_map = !args.no_source_map;
|
|
748
|
+
// A source map needs unmerged statement order, so it forces no optimization (same rule as
|
|
749
|
+
// `build --target js --source-map`).
|
|
750
|
+
let optimize = !args.no_optimize && !want_map;
|
|
751
|
+
let import_rewrite = if args.vite_dev {
|
|
752
|
+
tishlang_compile_js::ImportRewrite::ViteDev
|
|
753
|
+
} else {
|
|
754
|
+
tishlang_compile_js::ImportRewrite::Disk
|
|
755
|
+
};
|
|
756
|
+
let project_root = args
|
|
757
|
+
.project_root
|
|
758
|
+
.as_ref()
|
|
759
|
+
.map(PathBuf::from)
|
|
760
|
+
.or_else(|| input_path.parent().map(Path::to_path_buf));
|
|
761
|
+
let bundle = tishlang_compile_js::compile_module_esm(
|
|
762
|
+
&input_path,
|
|
763
|
+
project_root.as_deref(),
|
|
764
|
+
optimize,
|
|
765
|
+
import_rewrite,
|
|
766
|
+
want_map,
|
|
767
|
+
&args.jsx_import_source,
|
|
768
|
+
)
|
|
769
|
+
.map_err(|e| format!("{}", e))?;
|
|
770
|
+
|
|
771
|
+
if let Some(map_json) = bundle.source_map_json {
|
|
772
|
+
let map: serde_json::Value = serde_json::from_str(&map_json)
|
|
773
|
+
.map_err(|e| format!("Internal: source map is not valid JSON: {}", e))?;
|
|
774
|
+
let envelope = serde_json::json!({ "js": bundle.js, "map": map });
|
|
775
|
+
let line = serde_json::to_string(&envelope)
|
|
776
|
+
.map_err(|e| format!("Cannot serialize compile-module output: {}", e))?;
|
|
777
|
+
println!("{}", line);
|
|
778
|
+
} else {
|
|
779
|
+
print!("{}", bundle.js);
|
|
780
|
+
}
|
|
781
|
+
Ok(())
|
|
782
|
+
}
|
|
783
|
+
|
|
706
784
|
#[allow(clippy::vec_init_then_push, clippy::too_many_arguments)] // build_file maps CLI build flags 1:1
|
|
707
785
|
fn build_file(
|
|
708
786
|
input_path: &str,
|
|
@@ -715,6 +793,7 @@ fn build_file(
|
|
|
715
793
|
ios_triple: Option<&str>,
|
|
716
794
|
crate_type: &str,
|
|
717
795
|
format: &str,
|
|
796
|
+
jsx_import_source: &str,
|
|
718
797
|
) -> Result<(), String> {
|
|
719
798
|
let optimize = !no_optimize;
|
|
720
799
|
let input_path = Path::new(input_path)
|
|
@@ -724,7 +803,14 @@ fn build_file(
|
|
|
724
803
|
let is_js = input_path.extension().map(|e| e == "js") == Some(true);
|
|
725
804
|
|
|
726
805
|
if target == "js" {
|
|
727
|
-
return compile_to_js(
|
|
806
|
+
return compile_to_js(
|
|
807
|
+
&input_path,
|
|
808
|
+
output_path,
|
|
809
|
+
optimize,
|
|
810
|
+
source_map,
|
|
811
|
+
format,
|
|
812
|
+
jsx_import_source,
|
|
813
|
+
);
|
|
728
814
|
}
|
|
729
815
|
|
|
730
816
|
// `wasm-gpu` (#277): same pipeline as `wasm` but builds the `--features gpu` WebGPU runtime and
|
|
@@ -738,6 +738,183 @@ fn test_js_esm_export_collision() {
|
|
|
738
738
|
}
|
|
739
739
|
}
|
|
740
740
|
|
|
741
|
+
/// #284: `tish compile-module --vite-dev --source-map` compiles a single `.tish` file (no graph
|
|
742
|
+
/// resolution) to one ES module, keeps relative `.tish` specifiers, and emits a `{ js, map }` JSON
|
|
743
|
+
/// envelope whose map references the `.tish` source. This is the in-graph path the Vite plugin uses.
|
|
744
|
+
#[test]
|
|
745
|
+
fn test_compile_module_vite_dev_with_source_map() {
|
|
746
|
+
let bin = tish_bin();
|
|
747
|
+
if !bin.exists() {
|
|
748
|
+
return;
|
|
749
|
+
}
|
|
750
|
+
let main = workspace_root()
|
|
751
|
+
.join("tests")
|
|
752
|
+
.join("modules")
|
|
753
|
+
.join("esm")
|
|
754
|
+
.join("vite_hmr")
|
|
755
|
+
.join("main.tish");
|
|
756
|
+
if !main.exists() {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
let out = Command::new(&bin)
|
|
760
|
+
.args(["compile-module"])
|
|
761
|
+
.arg(&main)
|
|
762
|
+
.args([
|
|
763
|
+
"--target",
|
|
764
|
+
"js",
|
|
765
|
+
"--format",
|
|
766
|
+
"esm",
|
|
767
|
+
"--vite-dev",
|
|
768
|
+
"--source-map",
|
|
769
|
+
])
|
|
770
|
+
.current_dir(workspace_root())
|
|
771
|
+
.output()
|
|
772
|
+
.expect("run compile-module");
|
|
773
|
+
assert!(
|
|
774
|
+
out.status.success(),
|
|
775
|
+
"compile-module failed: stderr={}",
|
|
776
|
+
String::from_utf8_lossy(&out.stderr)
|
|
777
|
+
);
|
|
778
|
+
let stdout = String::from_utf8_lossy(&out.stdout);
|
|
779
|
+
let parsed: serde_json::Value =
|
|
780
|
+
serde_json::from_str(&stdout).unwrap_or_else(|e| panic!("stdout is not JSON: {e}\n{stdout}"));
|
|
781
|
+
let js = parsed["js"].as_str().expect("envelope has string `js`");
|
|
782
|
+
assert!(
|
|
783
|
+
js.contains("import { makeCounter } from \"./counter.tish\";"),
|
|
784
|
+
"Vite-dev keeps the .tish specifier:\n{js}"
|
|
785
|
+
);
|
|
786
|
+
assert!(
|
|
787
|
+
!js.contains("./counter.js"),
|
|
788
|
+
"Vite-dev must not rewrite .tish to .js:\n{js}"
|
|
789
|
+
);
|
|
790
|
+
let map = &parsed["map"];
|
|
791
|
+
assert!(map.is_object(), "envelope has object `map`: {map}");
|
|
792
|
+
assert_eq!(map["version"], serde_json::json!(3), "v3 source map");
|
|
793
|
+
let sources = map["sources"].as_array().expect("map has sources");
|
|
794
|
+
assert!(
|
|
795
|
+
sources
|
|
796
|
+
.iter()
|
|
797
|
+
.any(|s| s.as_str().map(|s| s.contains("main.tish")).unwrap_or(false)),
|
|
798
|
+
"map sources reference the .tish file: {sources:?}"
|
|
799
|
+
);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/// #284: without `--source-map`, `compile-module` prints raw ES module JS to stdout (no envelope),
|
|
803
|
+
/// so the output can be consumed directly.
|
|
804
|
+
#[test]
|
|
805
|
+
fn test_compile_module_no_source_map_prints_raw_js() {
|
|
806
|
+
let bin = tish_bin();
|
|
807
|
+
if !bin.exists() {
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
let counter = workspace_root()
|
|
811
|
+
.join("tests")
|
|
812
|
+
.join("modules")
|
|
813
|
+
.join("esm")
|
|
814
|
+
.join("vite_hmr")
|
|
815
|
+
.join("counter.tish");
|
|
816
|
+
if !counter.exists() {
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
let out = Command::new(&bin)
|
|
820
|
+
.args(["compile-module"])
|
|
821
|
+
.arg(&counter)
|
|
822
|
+
.args([
|
|
823
|
+
"--target",
|
|
824
|
+
"js",
|
|
825
|
+
"--format",
|
|
826
|
+
"esm",
|
|
827
|
+
"--vite-dev",
|
|
828
|
+
"--no-source-map",
|
|
829
|
+
])
|
|
830
|
+
.current_dir(workspace_root())
|
|
831
|
+
.output()
|
|
832
|
+
.expect("run compile-module");
|
|
833
|
+
assert!(
|
|
834
|
+
out.status.success(),
|
|
835
|
+
"compile-module failed: stderr={}",
|
|
836
|
+
String::from_utf8_lossy(&out.stderr)
|
|
837
|
+
);
|
|
838
|
+
let stdout = String::from_utf8_lossy(&out.stdout);
|
|
839
|
+
assert!(
|
|
840
|
+
stdout.contains("export function makeCounter"),
|
|
841
|
+
"raw JS output includes the export:\n{stdout}"
|
|
842
|
+
);
|
|
843
|
+
assert!(
|
|
844
|
+
!stdout.trim_start().starts_with('{'),
|
|
845
|
+
"no-source-map output is raw JS, not a JSON envelope:\n{stdout}"
|
|
846
|
+
);
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
/// #291: `compile-module` auto-imports the JSX runtime (`h` / `Fragment`) when a module uses JSX
|
|
850
|
+
/// but doesn't import them itself, so per-module ESM output doesn't throw `ReferenceError` at load.
|
|
851
|
+
/// `--jsx-import-source` overrides the runtime package.
|
|
852
|
+
#[test]
|
|
853
|
+
fn test_compile_module_jsx_auto_imports_runtime() {
|
|
854
|
+
let bin = tish_bin();
|
|
855
|
+
if !bin.exists() {
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
let widget = workspace_root()
|
|
859
|
+
.join("tests")
|
|
860
|
+
.join("modules")
|
|
861
|
+
.join("esm")
|
|
862
|
+
.join("vite_hmr")
|
|
863
|
+
.join("widget.tish");
|
|
864
|
+
if !widget.exists() {
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
// Default runtime source (`lattish`), Vite-dev so the specifier stays bare.
|
|
868
|
+
let out = Command::new(&bin)
|
|
869
|
+
.args(["compile-module"])
|
|
870
|
+
.arg(&widget)
|
|
871
|
+
.args([
|
|
872
|
+
"--target",
|
|
873
|
+
"js",
|
|
874
|
+
"--format",
|
|
875
|
+
"esm",
|
|
876
|
+
"--vite-dev",
|
|
877
|
+
"--no-source-map",
|
|
878
|
+
])
|
|
879
|
+
.current_dir(workspace_root())
|
|
880
|
+
.output()
|
|
881
|
+
.expect("run compile-module");
|
|
882
|
+
assert!(
|
|
883
|
+
out.status.success(),
|
|
884
|
+
"compile-module failed: stderr={}",
|
|
885
|
+
String::from_utf8_lossy(&out.stderr)
|
|
886
|
+
);
|
|
887
|
+
let stdout = String::from_utf8_lossy(&out.stdout);
|
|
888
|
+
assert!(
|
|
889
|
+
stdout.contains("import { h, Fragment } from \"lattish\";"),
|
|
890
|
+
"JSX module with a fragment auto-imports both h and Fragment:\n{stdout}"
|
|
891
|
+
);
|
|
892
|
+
|
|
893
|
+
// Custom runtime source via --jsx-import-source.
|
|
894
|
+
let out2 = Command::new(&bin)
|
|
895
|
+
.args(["compile-module"])
|
|
896
|
+
.arg(&widget)
|
|
897
|
+
.args([
|
|
898
|
+
"--target",
|
|
899
|
+
"js",
|
|
900
|
+
"--format",
|
|
901
|
+
"esm",
|
|
902
|
+
"--vite-dev",
|
|
903
|
+
"--no-source-map",
|
|
904
|
+
"--jsx-import-source",
|
|
905
|
+
"@tishlang/lattish",
|
|
906
|
+
])
|
|
907
|
+
.current_dir(workspace_root())
|
|
908
|
+
.output()
|
|
909
|
+
.expect("run compile-module");
|
|
910
|
+
assert!(out2.status.success());
|
|
911
|
+
let stdout2 = String::from_utf8_lossy(&out2.stdout);
|
|
912
|
+
assert!(
|
|
913
|
+
stdout2.contains("from \"@tishlang/lattish\";"),
|
|
914
|
+
"--jsx-import-source overrides the runtime package:\n{stdout2}"
|
|
915
|
+
);
|
|
916
|
+
}
|
|
917
|
+
|
|
741
918
|
/// Ignored: tishlang_eval::run() does not run the event loop.
|
|
742
919
|
#[test]
|
|
743
920
|
#[cfg(feature = "http")]
|