@tishlang/tish-format 3.9.1 → 3.10.2
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/Cargo.toml +0 -2
- package/bin/tish-format +0 -0
- package/crates/tish_compile/src/resolve.rs +91 -13
- package/crates/tish_fmt/Cargo.toml +1 -1
- package/crates/tish_native/src/build.rs +161 -26
- package/crates/tish_runtime_gba/Cargo.toml +10 -2
- package/crates/tish_runtime_gba/LICENSE +13 -0
- package/crates/tish_ui/src/jsx.rs +12 -1
- package/package.json +4 -2
- package/platform/darwin-arm64/tish-fmt +0 -0
- package/platform/darwin-x64/tish-fmt +0 -0
- package/platform/linux-arm64/tish-fmt +0 -0
- package/platform/linux-x64/tish-fmt +0 -0
- package/platform/win32-x64/tish-fmt.exe +0 -0
package/Cargo.toml
CHANGED
package/bin/tish-format
CHANGED
|
Binary file
|
|
@@ -756,31 +756,60 @@ pub fn compute_native_build_artifacts(
|
|
|
756
756
|
})
|
|
757
757
|
}
|
|
758
758
|
|
|
759
|
+
/// Names a directory may declare and still satisfy `package_name`.
|
|
760
|
+
///
|
|
761
|
+
/// A `tish:foo` import asks for the package `tish-foo`, which is what the in-repo crate
|
|
762
|
+
/// directories under `tish-apple/crates/` are called. The SAME code is published to npm under the
|
|
763
|
+
/// scoped name `@tishlang/tish-foo`, so a project that depends on the published package has it at
|
|
764
|
+
/// `node_modules/@tishlang/tish-foo` declaring that scoped name. Treat the two as one identity,
|
|
765
|
+
/// or a pinned published dependency is silently ignored in favour of a sibling checkout.
|
|
766
|
+
fn acceptable_package_names(package_name: &str) -> Vec<String> {
|
|
767
|
+
let mut names = vec![package_name.to_string()];
|
|
768
|
+
if !package_name.starts_with('@') {
|
|
769
|
+
names.push(format!("@tishlang/{package_name}"));
|
|
770
|
+
}
|
|
771
|
+
names
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
fn declares_one_of(pkg_dir: &Path, names: &[String]) -> bool {
|
|
775
|
+
let pkg_json = pkg_dir.join("package.json");
|
|
776
|
+
if !pkg_json.exists() {
|
|
777
|
+
return false;
|
|
778
|
+
}
|
|
779
|
+
match read_package_name(&pkg_json) {
|
|
780
|
+
Some(found) => names.iter().any(|n| *n == found),
|
|
781
|
+
None => false,
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
|
|
759
785
|
fn find_package_dir(package_name: &str, project_root: &Path) -> Result<PathBuf, String> {
|
|
786
|
+
let names = acceptable_package_names(package_name);
|
|
760
787
|
let mut search = project_root.to_path_buf();
|
|
761
788
|
loop {
|
|
789
|
+
// node_modules first, and the scoped published name before the sibling checkout: an
|
|
790
|
+
// explicit dependency pin must beat a directory that merely happens to sit alongside.
|
|
762
791
|
let node_mod = search.join("node_modules").join(package_name);
|
|
763
|
-
if node_mod
|
|
764
|
-
&& read_package_name(&node_mod.join("package.json")) == Some(package_name.to_string())
|
|
765
|
-
{
|
|
792
|
+
if declares_one_of(&node_mod, &names) {
|
|
766
793
|
return Ok(node_mod);
|
|
767
794
|
}
|
|
795
|
+
if !package_name.starts_with('@') {
|
|
796
|
+
let scoped = search
|
|
797
|
+
.join("node_modules")
|
|
798
|
+
.join("@tishlang")
|
|
799
|
+
.join(package_name);
|
|
800
|
+
if declares_one_of(&scoped, &names) {
|
|
801
|
+
return Ok(scoped);
|
|
802
|
+
}
|
|
803
|
+
}
|
|
768
804
|
let apple_crate = search.join("tish-apple").join("crates").join(package_name);
|
|
769
|
-
if apple_crate
|
|
770
|
-
&& read_package_name(&apple_crate.join("package.json"))
|
|
771
|
-
== Some(package_name.to_string())
|
|
772
|
-
{
|
|
805
|
+
if declares_one_of(&apple_crate, &names) {
|
|
773
806
|
return Ok(apple_crate);
|
|
774
807
|
}
|
|
775
808
|
let sibling = search.join(package_name);
|
|
776
|
-
if sibling
|
|
777
|
-
&& read_package_name(&sibling.join("package.json")) == Some(package_name.to_string())
|
|
778
|
-
{
|
|
809
|
+
if declares_one_of(&sibling, &names) {
|
|
779
810
|
return Ok(sibling);
|
|
780
811
|
}
|
|
781
|
-
if search
|
|
782
|
-
&& read_package_name(&search.join("package.json")) == Some(package_name.to_string())
|
|
783
|
-
{
|
|
812
|
+
if declares_one_of(&search, &names) {
|
|
784
813
|
return Ok(search);
|
|
785
814
|
}
|
|
786
815
|
if let Some(parent) = search.parent() {
|
|
@@ -2385,4 +2414,53 @@ mod find_package_dir_tests {
|
|
|
2385
2414
|
let hit = find_package_dir("tish-macos", &project).expect("resolve");
|
|
2386
2415
|
assert_eq!(hit.canonicalize().unwrap(), apple.canonicalize().unwrap());
|
|
2387
2416
|
}
|
|
2417
|
+
|
|
2418
|
+
/// The published npm package for `tish:macos` is named `@tishlang/tish-macos`, so a bare
|
|
2419
|
+
/// name-equality check rejects it and silently falls through to a sibling checkout --
|
|
2420
|
+
/// pulling that checkout's path-dep copy of tishlang_core in beside the registry one and
|
|
2421
|
+
/// failing the build on mismatched `Value` types. An explicit dependency must win.
|
|
2422
|
+
#[test]
|
|
2423
|
+
fn prefers_scoped_node_modules_over_tish_apple_crates() {
|
|
2424
|
+
let dir = tempfile::tempdir().expect("tempdir");
|
|
2425
|
+
let root = dir.path();
|
|
2426
|
+
let apple = root.join("tish-apple").join("crates").join("tish-macos");
|
|
2427
|
+
std::fs::create_dir_all(&apple).unwrap();
|
|
2428
|
+
std::fs::write(
|
|
2429
|
+
apple.join("package.json"),
|
|
2430
|
+
r#"{"name":"tish-macos","tish":{"module":true,"crate":"tishlang_macos","export":"macos_object"}}"#,
|
|
2431
|
+
)
|
|
2432
|
+
.unwrap();
|
|
2433
|
+
let project = root.join("app");
|
|
2434
|
+
let scoped = project
|
|
2435
|
+
.join("node_modules")
|
|
2436
|
+
.join("@tishlang")
|
|
2437
|
+
.join("tish-macos");
|
|
2438
|
+
std::fs::create_dir_all(&scoped).unwrap();
|
|
2439
|
+
std::fs::write(
|
|
2440
|
+
scoped.join("package.json"),
|
|
2441
|
+
r#"{"name":"@tishlang/tish-macos","tish":{"module":true,"crate":"tishlang_macos","export":"macos_object"}}"#,
|
|
2442
|
+
)
|
|
2443
|
+
.unwrap();
|
|
2444
|
+
let hit = find_package_dir("tish-macos", &project).expect("resolve");
|
|
2445
|
+
assert_eq!(hit.canonicalize().unwrap(), scoped.canonicalize().unwrap());
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
/// npm alias installs (`"tish-macos": "npm:@tishlang/tish-macos@1.2.0"`) put the scoped
|
|
2449
|
+
/// package at the UNSCOPED directory, so the directory name matches but the declared name
|
|
2450
|
+
/// does not. That must resolve too.
|
|
2451
|
+
#[test]
|
|
2452
|
+
fn accepts_scoped_name_at_unscoped_node_modules_dir() {
|
|
2453
|
+
let dir = tempfile::tempdir().expect("tempdir");
|
|
2454
|
+
let root = dir.path();
|
|
2455
|
+
let project = root.join("app");
|
|
2456
|
+
let aliased = project.join("node_modules").join("tish-macos");
|
|
2457
|
+
std::fs::create_dir_all(&aliased).unwrap();
|
|
2458
|
+
std::fs::write(
|
|
2459
|
+
aliased.join("package.json"),
|
|
2460
|
+
r#"{"name":"@tishlang/tish-macos","tish":{"module":true,"crate":"tishlang_macos","export":"macos_object"}}"#,
|
|
2461
|
+
)
|
|
2462
|
+
.unwrap();
|
|
2463
|
+
let hit = find_package_dir("tish-macos", &project).expect("resolve");
|
|
2464
|
+
assert_eq!(hit.canonicalize().unwrap(), aliased.canonicalize().unwrap());
|
|
2465
|
+
}
|
|
2388
2466
|
}
|
|
@@ -224,18 +224,7 @@ pub fn build_via_cargo_with_config(
|
|
|
224
224
|
rust_main
|
|
225
225
|
};
|
|
226
226
|
|
|
227
|
-
let
|
|
228
|
-
.parent()
|
|
229
|
-
.ok_or_else(|| "invalid tishlang_runtime path (no parent)".to_string())?
|
|
230
|
-
.join("tish_ui");
|
|
231
|
-
let ui_dep = if rust_code.contains("tishlang_ui") {
|
|
232
|
-
format!(
|
|
233
|
-
"\ntishlang_ui = {{ path = {:?}, default-features = false, features = [\"runtime\"] }}\n",
|
|
234
|
-
tish_ui_path.display().to_string().replace('\\', "/")
|
|
235
|
-
)
|
|
236
|
-
} else {
|
|
237
|
-
String::new()
|
|
238
|
-
};
|
|
227
|
+
let ui_dep = ui_dep_toml(&runtime_path, rust_code);
|
|
239
228
|
|
|
240
229
|
let profile = nested_release_profile_toml();
|
|
241
230
|
let src_file = if build_config.artifact == NativeArtifact::StaticLib {
|
|
@@ -271,9 +260,18 @@ edition = "2021"
|
|
|
271
260
|
|
|
272
261
|
{}{}
|
|
273
262
|
[dependencies]
|
|
274
|
-
|
|
275
|
-
{}{}"#,
|
|
276
|
-
crate_section,
|
|
263
|
+
{}
|
|
264
|
+
{}{}{}"#,
|
|
265
|
+
crate_section,
|
|
266
|
+
profile,
|
|
267
|
+
runtime_dep_toml(&runtime_path, &features_str),
|
|
268
|
+
more_deps,
|
|
269
|
+
ui_dep,
|
|
270
|
+
if released_compiler_version().is_some() {
|
|
271
|
+
String::new()
|
|
272
|
+
} else {
|
|
273
|
+
tishlang_patch_section(&runtime_path, &more_deps)
|
|
274
|
+
}
|
|
277
275
|
);
|
|
278
276
|
|
|
279
277
|
fs::write(build_dir.join("Cargo.toml"), cargo_toml)
|
|
@@ -452,6 +450,141 @@ opt-level = 3
|
|
|
452
450
|
}
|
|
453
451
|
|
|
454
452
|
/// Read `version = "…"` from the `[package]` section of a crate's `Cargo.toml`.
|
|
453
|
+
/// The `tishlang_runtime` dependency line: registry version for a released compiler,
|
|
454
|
+
/// local path tree for dev builds.
|
|
455
|
+
fn runtime_dep_toml(runtime_path: &str, features_str: &str) -> String {
|
|
456
|
+
if let Some(v) = released_compiler_version() {
|
|
457
|
+
format!("tishlang_runtime = {{ version = {:?}{} }}", v, features_str)
|
|
458
|
+
} else {
|
|
459
|
+
format!("tishlang_runtime = {{ path = {:?}{} }}", runtime_path, features_str)
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/// The optional `tishlang_ui` dependency line (same source policy as the runtime).
|
|
464
|
+
fn ui_dep_toml(runtime_path: &str, rust_code: &str) -> String {
|
|
465
|
+
if !rust_code.contains("tishlang_ui") {
|
|
466
|
+
return String::new();
|
|
467
|
+
}
|
|
468
|
+
if let Some(v) = released_compiler_version() {
|
|
469
|
+
return format!(
|
|
470
|
+
"\ntishlang_ui = {{ version = {:?}, default-features = false, features = [\"runtime\"] }}\n",
|
|
471
|
+
v
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
let tish_ui_path = std::path::Path::new(runtime_path)
|
|
475
|
+
.parent()
|
|
476
|
+
.map(|p| p.join("tish_ui"))
|
|
477
|
+
.unwrap_or_default();
|
|
478
|
+
format!(
|
|
479
|
+
"\ntishlang_ui = {{ path = {:?}, default-features = false, features = [\"runtime\"] }}\n",
|
|
480
|
+
tish_ui_path.display().to_string().replace('\\', "/")
|
|
481
|
+
)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/// The compiler's own RELEASED version, or None for a dev/workspace build.
|
|
485
|
+
///
|
|
486
|
+
/// A released compiler is published together with the whole tishlang_* crate family at the
|
|
487
|
+
/// SAME version, so generated crates can depend on the runtime from crates.io — one source
|
|
488
|
+
/// for every tishlang crate, unified with any published native crate (tishlang_ios,
|
|
489
|
+
/// tishlang_desktop, user `cargo:` deps). Dev builds (workspace version 0.x / -dev) keep
|
|
490
|
+
/// the local path tree + the [patch.crates-io] pin instead.
|
|
491
|
+
fn released_compiler_version() -> Option<&'static str> {
|
|
492
|
+
let v = env!("CARGO_PKG_VERSION");
|
|
493
|
+
if v.starts_with("0.") || v.contains("dev") {
|
|
494
|
+
None
|
|
495
|
+
} else {
|
|
496
|
+
Some(v)
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/// `[package] name` from a crate dir's Cargo.toml (first table only, like read_crate_version).
|
|
501
|
+
fn read_crate_package_name(crate_dir: &Path) -> Option<String> {
|
|
502
|
+
let toml = fs::read_to_string(crate_dir.join("Cargo.toml")).ok()?;
|
|
503
|
+
for line in toml.lines() {
|
|
504
|
+
let line = line.trim();
|
|
505
|
+
if let Some(rest) = line.strip_prefix("name") {
|
|
506
|
+
let rest = rest.trim_start();
|
|
507
|
+
if let Some(rest) = rest.strip_prefix('=') {
|
|
508
|
+
return Some(rest.trim().trim_matches('"').to_string());
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if line.starts_with('[') && !line.starts_with("[package]") {
|
|
512
|
+
break;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
None
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/// `[patch.crates-io]` section pinning every `tishlang_*` crate in the local runtime tree
|
|
519
|
+
/// (the siblings of `runtime_path`) to that tree.
|
|
520
|
+
///
|
|
521
|
+
/// Why: the generated program depends on `tishlang_runtime` BY PATH, but registry-sourced
|
|
522
|
+
/// native crates (`cargo:` deps with a version, published hosts like `tishlang_ios` /
|
|
523
|
+
/// `tishlang_desktop`) declare `tishlang_core` / `tishlang_runtime` / `tishlang_ui` BY
|
|
524
|
+
/// VERSION. Cargo never unifies a path crate with a registry crate, so the build died with
|
|
525
|
+
/// "multiple different versions of crate `tishlang_core`" the moment a published native
|
|
526
|
+
/// crate entered the graph — publishing runtimes was pointless. The patch makes the
|
|
527
|
+
/// compiler's own tree the single source for every tishlang crate, whatever requested it.
|
|
528
|
+
///
|
|
529
|
+
/// Emitted whenever the program has ANY extra native dependency: even a path dep (an npm-
|
|
530
|
+
/// shipped crate like `@tishlang/tish-ios`) reaches the registry TRANSITIVELY through its own
|
|
531
|
+
/// `tishlang_core = "x"` version requirements. Builds with no native deps skip the section so
|
|
532
|
+
/// plain programs don't carry "unused patch" warnings.
|
|
533
|
+
fn tishlang_patch_section(runtime_path: &str, more_deps: &str) -> String {
|
|
534
|
+
let has_extra_dep = more_deps.lines().any(|l| {
|
|
535
|
+
let l = l.trim();
|
|
536
|
+
!l.is_empty() && l.contains('=') && !l.starts_with('#')
|
|
537
|
+
});
|
|
538
|
+
if !has_extra_dep {
|
|
539
|
+
return String::new();
|
|
540
|
+
}
|
|
541
|
+
// A patch entry only ever applies when the patched source's version SATISFIES the
|
|
542
|
+
// registry requirement it replaces. Dev/workspace trees carry 0.x placeholder
|
|
543
|
+
// versions that can never satisfy a released "3.x" requirement — emitting the
|
|
544
|
+
// patch there does nothing useful and destabilizes resolution for path-dep
|
|
545
|
+
// setups that already work. Only patch from a release-stamped tree.
|
|
546
|
+
let core_dir = Path::new(runtime_path)
|
|
547
|
+
.parent()
|
|
548
|
+
.map(|p| p.join("tish_core"));
|
|
549
|
+
let tree_is_released = core_dir
|
|
550
|
+
.as_deref()
|
|
551
|
+
.and_then(read_crate_version)
|
|
552
|
+
.map(|v| !v.starts_with("0."))
|
|
553
|
+
.unwrap_or(false);
|
|
554
|
+
if !tree_is_released {
|
|
555
|
+
return String::new();
|
|
556
|
+
}
|
|
557
|
+
let Some(crates_dir) = Path::new(runtime_path).parent() else {
|
|
558
|
+
return String::new();
|
|
559
|
+
};
|
|
560
|
+
let Ok(read) = fs::read_dir(crates_dir) else {
|
|
561
|
+
return String::new();
|
|
562
|
+
};
|
|
563
|
+
let mut entries: Vec<(String, String)> = Vec::new();
|
|
564
|
+
for e in read.flatten() {
|
|
565
|
+
let dir = e.path();
|
|
566
|
+
if !dir.join("Cargo.toml").exists() {
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
let Some(name) = read_crate_package_name(&dir) else {
|
|
570
|
+
continue;
|
|
571
|
+
};
|
|
572
|
+
if !name.starts_with("tishlang_") {
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
entries.push((name, dir.display().to_string().replace('\\', "/")));
|
|
576
|
+
}
|
|
577
|
+
if entries.is_empty() {
|
|
578
|
+
return String::new();
|
|
579
|
+
}
|
|
580
|
+
entries.sort();
|
|
581
|
+
let mut out = String::from("\n[patch.crates-io]\n");
|
|
582
|
+
for (name, path) in entries {
|
|
583
|
+
out.push_str(&format!("{} = {{ path = {:?} }}\n", name, path));
|
|
584
|
+
}
|
|
585
|
+
out
|
|
586
|
+
}
|
|
587
|
+
|
|
455
588
|
fn read_crate_version(crate_dir: &Path) -> Option<String> {
|
|
456
589
|
let toml = fs::read_to_string(crate_dir.join("Cargo.toml")).ok()?;
|
|
457
590
|
for line in toml.lines() {
|
|
@@ -925,15 +1058,8 @@ pub(crate) fn build_many_via_cargo(
|
|
|
925
1058
|
more_deps.push_str("\nmimalloc = \"0.1\"\n");
|
|
926
1059
|
}
|
|
927
1060
|
|
|
928
|
-
let tish_ui_path = std::path::Path::new(&runtime_path)
|
|
929
|
-
.parent()
|
|
930
|
-
.ok_or_else(|| "invalid tishlang_runtime path (no parent)".to_string())?
|
|
931
|
-
.join("tish_ui");
|
|
932
1061
|
let ui_dep = if needs_ui {
|
|
933
|
-
|
|
934
|
-
"\ntishlang_ui = {{ path = {:?}, default-features = false, features = [\"runtime\"] }}\n",
|
|
935
|
-
tish_ui_path.display().to_string().replace('\\', "/")
|
|
936
|
-
)
|
|
1062
|
+
ui_dep_toml(&runtime_path, "tishlang_ui")
|
|
937
1063
|
} else {
|
|
938
1064
|
String::new()
|
|
939
1065
|
};
|
|
@@ -979,9 +1105,18 @@ edition = "2021"
|
|
|
979
1105
|
|
|
980
1106
|
{}{}
|
|
981
1107
|
[dependencies]
|
|
982
|
-
|
|
983
|
-
{}{}"#,
|
|
984
|
-
bin_tables,
|
|
1108
|
+
{}
|
|
1109
|
+
{}{}{}"#,
|
|
1110
|
+
bin_tables,
|
|
1111
|
+
profile,
|
|
1112
|
+
runtime_dep_toml(&runtime_path, &features_str),
|
|
1113
|
+
more_deps,
|
|
1114
|
+
ui_dep,
|
|
1115
|
+
if released_compiler_version().is_some() {
|
|
1116
|
+
String::new()
|
|
1117
|
+
} else {
|
|
1118
|
+
tishlang_patch_section(&runtime_path, &more_deps)
|
|
1119
|
+
}
|
|
985
1120
|
);
|
|
986
1121
|
|
|
987
1122
|
fs::write(build_dir.join("Cargo.toml"), cargo_toml)
|
|
@@ -3,6 +3,14 @@ name = "tishlang_runtime_gba"
|
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "no_std runtime facade for Tish compiled output on the Game Boy Advance (agb)"
|
|
6
|
+
# Spelled out, NOT `{ workspace = true }`: this crate is in the workspace `exclude` list, so it has
|
|
7
|
+
# no workspace root to inherit from. Without these, `cargo publish` refuses the crate outright,
|
|
8
|
+
# which is why it is the one tishlang_* crate that never shipped.
|
|
9
|
+
#
|
|
10
|
+
# The LICENSE is a COPY, not the root one: cargo requires license-file to resolve inside the
|
|
11
|
+
# package directory, and `../../LICENSE` is not packaged.
|
|
12
|
+
license-file = "LICENSE"
|
|
13
|
+
repository = "https://github.com/tishlang/tish"
|
|
6
14
|
|
|
7
15
|
# The GBA `Gba` emit mode declares the generated crate's dependency as
|
|
8
16
|
# tishlang_runtime = { package = "tishlang_runtime_gba", path = ... }
|
|
@@ -11,6 +19,6 @@ description = "no_std runtime facade for Tish compiled output on the Game Boy Ad
|
|
|
11
19
|
# tishlang_core / tishlang_builtins and adds the GBA `gba::{init, halt, hooks}`.
|
|
12
20
|
|
|
13
21
|
[dependencies]
|
|
14
|
-
tishlang_core = { path = "../tish_core", default-features = false, features = ["portable"] }
|
|
15
|
-
tishlang_builtins = { path = "../tish_builtins", default-features = false, features = ["portable"] }
|
|
22
|
+
tishlang_core = { path = "../tish_core", version = ">=0.1", default-features = false, features = ["portable"] }
|
|
23
|
+
tishlang_builtins = { path = "../tish_builtins", version = ">=0.1", default-features = false, features = ["portable"] }
|
|
16
24
|
agb = "0.25.0"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Pay It Forward License (PIF)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-present The Tish Project Authors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
This license includes a perpetual, worldwide, non-exclusive, royalty-free, irrevocable (except as stated below) grant for patent claims necessarily infringed by the use of the Software or any contributions submitted to it; terminating automatically when an entity initiates patent litigation (including a cross-claim or counterclaim) alleging that the Software or any portion thereof infringes a patent.
|
|
10
|
+
|
|
11
|
+
The software is provided "as is," without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and non-infringement. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software.
|
|
12
|
+
|
|
13
|
+
Recipients of the Software should pay it forward by contributing to the open-source community through actions including but not limited to providing code, documentation, tutorials, guides, support, feedback, or promoting open-source projects through advocacy or related efforts that advance innovation and community growth.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
//! Shared JSX lowering: emit `h(tag, props, children)` as JavaScript or Rust (`Value`) source.
|
|
2
2
|
|
|
3
3
|
use std::collections::HashSet;
|
|
4
|
+
use std::sync::Arc;
|
|
4
5
|
|
|
5
6
|
use tishlang_ast::{
|
|
6
7
|
ArrayElement, ArrowBody, CallArg, ExportDeclaration, Expr, JsxAttrValue, JsxChild, JsxProp,
|
|
@@ -401,6 +402,7 @@ where
|
|
|
401
402
|
match expr {
|
|
402
403
|
Expr::JsxElement {
|
|
403
404
|
tag,
|
|
405
|
+
tag_span,
|
|
404
406
|
props,
|
|
405
407
|
children,
|
|
406
408
|
..
|
|
@@ -412,7 +414,16 @@ where
|
|
|
412
414
|
.unwrap_or(false);
|
|
413
415
|
let tag_rust = if is_component {
|
|
414
416
|
if fun_decls.contains(tag.as_ref()) {
|
|
415
|
-
|
|
417
|
+
// Lower the component reference through the caller's own identifier path
|
|
418
|
+
// rather than writing the bare name. A module-scope function is promoted to a
|
|
419
|
+
// `__TISH_GF_<name>` static, and there is no local of the original name to
|
|
420
|
+
// reference — emitting it verbatim produced
|
|
421
|
+
// `error[E0425]: cannot find value \`Comp\` in this scope` for every imported
|
|
422
|
+
// component. `emit_expr` already resolves statics, locals and captures.
|
|
423
|
+
emit_expr(&Expr::Ident {
|
|
424
|
+
name: Arc::clone(tag),
|
|
425
|
+
span: *tag_span,
|
|
426
|
+
})?
|
|
416
427
|
} else {
|
|
417
428
|
format!("Value::String({:?}.into())", tag.as_ref())
|
|
418
429
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tishlang/tish-format",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.10.2",
|
|
4
4
|
"description": "Tish code formatter",
|
|
5
5
|
"license": "PIF",
|
|
6
6
|
"repository": {
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
"tish-format": "./bin/tish-format"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"postinstall": "node scripts/install-bin.js"
|
|
17
|
+
"postinstall": "node scripts/install-bin.js",
|
|
18
|
+
"prepack": "node scripts/prepack.js",
|
|
19
|
+
"postpack": "node scripts/postpack.js"
|
|
18
20
|
},
|
|
19
21
|
"files": [
|
|
20
22
|
"bin",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|