@tishlang/tish-lint 2.12.0 → 2.35.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/Cargo.toml +3 -0
- package/bin/tish-lint +0 -0
- package/crates/js_to_tish/src/transform/expr.rs +12 -2
- package/crates/tish/tests/fixtures/fs_parity_callbacks.tish +22 -0
- package/crates/tish/tests/fixtures/fs_parity_promises.tish +21 -0
- package/crates/tish/tests/fixtures/fs_parity_sync.tish +20 -0
- package/crates/tish/tests/fs_parity.rs +103 -0
- package/crates/tish/tests/integration_test.rs +80 -0
- package/crates/tish/tests/shortcircuit.rs +3 -3
- package/crates/tish_ast/src/ast.rs +84 -0
- package/crates/tish_builtins/Cargo.toml +1 -0
- package/crates/tish_builtins/src/array.rs +724 -72
- package/crates/tish_builtins/src/collections.rs +149 -40
- package/crates/tish_builtins/src/globals.rs +215 -25
- package/crates/tish_builtins/src/math.rs +65 -7
- package/crates/tish_builtins/src/number.rs +173 -0
- package/crates/tish_builtins/src/string.rs +263 -23
- package/crates/tish_bytecode/src/chunk.rs +7 -0
- package/crates/tish_bytecode/src/compiler.rs +611 -63
- package/crates/tish_bytecode/src/lib.rs +1 -1
- package/crates/tish_bytecode/src/opcode.rs +156 -2
- package/crates/tish_bytecode/src/serialize.rs +2 -0
- package/crates/tish_bytecode/tests/append_local_string_builder.rs +63 -0
- package/crates/tish_bytecode/tests/math_unary_intrinsic.rs +47 -0
- package/crates/tish_compile/src/codegen.rs +18219 -5283
- package/crates/tish_compile/src/infer.rs +1562 -30
- package/crates/tish_compile/src/lib.rs +29 -4
- package/crates/tish_compile/src/resolve.rs +151 -13
- package/crates/tish_compile/src/types.rs +224 -28
- package/crates/tish_compile/tests/dump_codegen.rs +21 -0
- package/crates/tish_compile/tests/perf_codegen_169_173.rs +8 -17
- package/crates/tish_compile/tests/perf_codegen_173_part3.rs +61 -0
- package/crates/tish_compile/tests/perf_codegen_174.rs +160 -0
- package/crates/tish_compile/tests/perf_codegen_175.rs +190 -0
- package/crates/tish_compile/tests/perf_codegen_176.rs +60 -0
- package/crates/tish_compile/tests/perf_codegen_177.rs +167 -0
- package/crates/tish_compile/tests/perf_codegen_178.rs +114 -0
- package/crates/tish_compile/tests/perf_codegen_178_rec.rs +124 -0
- package/crates/tish_compile/tests/perf_codegen_181.rs +36 -0
- package/crates/tish_compile/tests/perf_codegen_320.rs +211 -0
- package/crates/tish_compile/tests/perf_codegen_module_const_forof.rs +40 -0
- package/crates/tish_compile_js/src/codegen.rs +94 -3
- package/crates/tish_compile_js/src/tests_jsx.rs +27 -0
- package/crates/tish_compiler_wasm/src/resolve_virtual.rs +115 -2
- package/crates/tish_core/Cargo.toml +4 -0
- package/crates/tish_core/src/json.rs +109 -6
- package/crates/tish_core/src/lib.rs +222 -2
- package/crates/tish_core/src/shape.rs +4 -2
- package/crates/tish_core/src/uri.rs +45 -0
- package/crates/tish_core/src/value.rs +571 -35
- package/crates/tish_core/src/vmref.rs +14 -0
- package/crates/tish_eval/Cargo.toml +2 -1
- package/crates/tish_eval/src/eval.rs +1328 -101
- package/crates/tish_eval/src/natives.rs +283 -18
- package/crates/tish_eval/src/regex.rs +47 -1
- package/crates/tish_eval/src/value.rs +76 -21
- package/crates/tish_ffi/src/lib.rs +11 -1
- package/crates/tish_ffi/tests/double_free.rs +35 -0
- package/crates/tish_fmt/src/lib.rs +94 -1
- package/crates/tish_lexer/src/lib.rs +76 -0
- package/crates/tish_lexer/src/token.rs +4 -0
- package/crates/tish_lint/Cargo.toml +1 -1
- package/crates/tish_lint/src/lib.rs +126 -0
- package/crates/tish_lsp/README.md +2 -1
- package/crates/tish_lsp/src/main.rs +378 -28
- package/crates/tish_native/src/build.rs +41 -0
- package/crates/tish_opt/src/lib.rs +20 -1
- package/crates/tish_parser/Cargo.toml +4 -0
- package/crates/tish_parser/src/lib.rs +68 -0
- package/crates/tish_parser/src/parser.rs +479 -28
- package/crates/tish_resolve/src/lib.rs +75 -5
- package/crates/tish_runtime/Cargo.toml +10 -1
- package/crates/tish_runtime/src/fs_ext.rs +359 -0
- package/crates/tish_runtime/src/http.rs +28 -10
- package/crates/tish_runtime/src/http_fetch.rs +150 -1
- package/crates/tish_runtime/src/http_hyper.rs +41 -18
- package/crates/tish_runtime/src/http_prefork.rs +72 -11
- package/crates/tish_runtime/src/lib.rs +651 -51
- package/crates/tish_runtime/src/timers.rs +49 -2
- package/crates/tish_ui/src/jsx.rs +21 -3
- package/crates/tish_vm/src/jit.rs +2514 -117
- package/crates/tish_vm/src/vm.rs +1479 -224
- package/package.json +1 -1
- package/platform/darwin-arm64/tish-lint +0 -0
- package/platform/darwin-x64/tish-lint +0 -0
- package/platform/linux-arm64/tish-lint +0 -0
- package/platform/linux-x64/tish-lint +0 -0
- package/platform/win32-x64/tish-lint.exe +0 -0
|
@@ -10,6 +10,25 @@ mod types;
|
|
|
10
10
|
|
|
11
11
|
pub use check::{check_program, TypeDiagnostic};
|
|
12
12
|
|
|
13
|
+
/// The native typed-codegen optimizations — numeric param inference, struct/aggregate inference,
|
|
14
|
+
/// native (monomorphic) free fns, native-vec params, recursive-struct arena lowering, fused/native
|
|
15
|
+
/// higher-order fns, and native `number[]` params — are **ON BY DEFAULT**. There are no per-pass
|
|
16
|
+
/// flags anymore: that per-flag gating caused repeated "did I set all of them?" drift between the
|
|
17
|
+
/// gauntlet, manual builds, and CI. The single escape hatch `TISH_NATIVE_OPT=0` turns the whole
|
|
18
|
+
/// stack off — used only by the gauntlet's boxed A/B baseline and to bisect a suspected miscompile.
|
|
19
|
+
pub(crate) fn native_opts_enabled() -> bool {
|
|
20
|
+
std::env::var("TISH_NATIVE_OPT").map(|v| v != "0").unwrap_or(true)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// #381 — the native recursion guard: rotation copies for self/mutually-recursive typed fns plus a
|
|
24
|
+
/// depth guard at boxed user-fn closure entry, so unbounded recursion raises a catchable
|
|
25
|
+
/// `RangeError` instead of overflowing the stack (an uncatchable process abort). **Default ON**;
|
|
26
|
+
/// `TISH_NATIVE_RECUR_GUARD=0` turns it off — mirrors the VM JIT tier's `TISH_JIT_RECUR_GUARD`
|
|
27
|
+
/// (for bisection and code-size-sensitive builds; unbounded recursion then aborts again, as before).
|
|
28
|
+
pub(crate) fn native_recur_guard_enabled() -> bool {
|
|
29
|
+
std::env::var("TISH_NATIVE_RECUR_GUARD").map(|v| v != "0").unwrap_or(true)
|
|
30
|
+
}
|
|
31
|
+
|
|
13
32
|
/// How generated Rust is linked (desktop binary vs embedded iOS staticlib).
|
|
14
33
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
|
15
34
|
pub enum NativeEmitMode {
|
|
@@ -88,8 +107,10 @@ fn count(): number {
|
|
|
88
107
|
|
|
89
108
|
#[test]
|
|
90
109
|
fn loop_var_decl_clone_outer_var() {
|
|
91
|
-
//
|
|
92
|
-
//
|
|
110
|
+
// outerVar = 42 is inferred as f64. Per #313, a top-level numeric used ONLY at top level
|
|
111
|
+
// (never inside a function/closure body) is a native `run()`-local `let mut _: f64`, NOT a
|
|
112
|
+
// `thread_local Cell<f64>` — the Cell is reserved for globals a function reads across calls
|
|
113
|
+
// (e.g. fasta's `seed`). The read `let x = outerVar` loads it as a Copy f64.
|
|
93
114
|
let src = r#"
|
|
94
115
|
let outerVar = 42
|
|
95
116
|
for (let i = 0; i < 5; i = i + 1) {
|
|
@@ -98,10 +119,14 @@ for (let i = 0; i < 5; i = i + 1) {
|
|
|
98
119
|
"#;
|
|
99
120
|
let program = parse(src).unwrap();
|
|
100
121
|
let rust = compile(&program).unwrap();
|
|
101
|
-
// outerVar
|
|
122
|
+
// outerVar is a native f64 local (no TLS Cell, since no function references it); x reads it.
|
|
102
123
|
assert!(
|
|
103
124
|
rust.contains("let mut outerVar: f64"),
|
|
104
|
-
"expected outerVar
|
|
125
|
+
"expected outerVar as a native f64 local (#313)"
|
|
126
|
+
);
|
|
127
|
+
assert!(
|
|
128
|
+
!rust.contains("G_OUTERVAR"),
|
|
129
|
+
"outerVar must NOT be a thread_local Cell global — it is top-level-only (#313)"
|
|
105
130
|
);
|
|
106
131
|
assert!(rust.contains("let mut x: f64"), "expected x: f64");
|
|
107
132
|
}
|
|
@@ -49,17 +49,23 @@ pub struct NativeBuildArtifacts {
|
|
|
49
49
|
pub native_init: std::collections::HashMap<String, NativeModuleInit>,
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
/// Node-compatible aliases for built-in modules (fs -> tish:fs, etc.).
|
|
52
|
+
/// Node-compatible aliases for built-in modules (fs -> tish:fs, etc.). The `node:` prefix
|
|
53
|
+
/// (e.g. `node:fs`, `node:fs/promises`) is stripped before lookup.
|
|
53
54
|
const BUILTIN_ALIASES: &[(&str, &str)] = &[
|
|
54
55
|
("fs", "tish:fs"),
|
|
56
|
+
("fs/promises", "tish:fs/promises"),
|
|
55
57
|
("http", "tish:http"),
|
|
56
58
|
("timers", "tish:timers"),
|
|
57
59
|
("process", "tish:process"),
|
|
58
60
|
("ws", "tish:ws"),
|
|
61
|
+
("tty", "tish:tty"),
|
|
59
62
|
];
|
|
60
63
|
|
|
61
|
-
/// Normalize built-in spec to canonical form.
|
|
64
|
+
/// Normalize built-in spec to canonical form. Handles the Node `node:` prefix
|
|
65
|
+
/// (`node:fs` -> `tish:fs`, `node:fs/promises` -> `tish:fs/promises`) and bare aliases.
|
|
62
66
|
pub fn normalize_builtin_spec(spec: &str) -> Option<String> {
|
|
67
|
+
// Strip a leading `node:` so `node:fs` resolves the same as `fs`.
|
|
68
|
+
let spec = spec.strip_prefix("node:").unwrap_or(spec);
|
|
63
69
|
if spec.starts_with("tish:") {
|
|
64
70
|
return Some(spec.to_string());
|
|
65
71
|
}
|
|
@@ -71,10 +77,20 @@ pub fn normalize_builtin_spec(spec: &str) -> Option<String> {
|
|
|
71
77
|
|
|
72
78
|
/// Built-in modules that come from tishlang_runtime, not from package.json.
|
|
73
79
|
pub fn is_builtin_native_spec(spec: &str) -> bool {
|
|
80
|
+
let spec = spec.strip_prefix("node:").unwrap_or(spec);
|
|
74
81
|
matches!(
|
|
75
82
|
spec,
|
|
76
|
-
"tish:fs"
|
|
77
|
-
|
|
83
|
+
"tish:fs"
|
|
84
|
+
| "tish:fs/promises"
|
|
85
|
+
| "tish:http"
|
|
86
|
+
| "tish:timers"
|
|
87
|
+
| "tish:process"
|
|
88
|
+
| "tish:ws"
|
|
89
|
+
| "tish:tty"
|
|
90
|
+
) || matches!(
|
|
91
|
+
spec,
|
|
92
|
+
"fs" | "fs/promises" | "http" | "timers" | "process" | "ws" | "tty"
|
|
93
|
+
)
|
|
78
94
|
}
|
|
79
95
|
|
|
80
96
|
/// Resolve all native imports in a merged program via package.json lookup.
|
|
@@ -238,9 +254,12 @@ pub fn program_uses_document(program: &Program) -> bool {
|
|
|
238
254
|
|| update.as_ref().is_some_and(expr_uses_document)
|
|
239
255
|
|| stmt_uses_document(body)
|
|
240
256
|
}
|
|
241
|
-
Statement::ForOf { iterable, body, .. }
|
|
242
|
-
|
|
243
|
-
|
|
257
|
+
Statement::ForOf { iterable, body, .. }
|
|
258
|
+
| Statement::ForIn {
|
|
259
|
+
object: iterable,
|
|
260
|
+
body,
|
|
261
|
+
..
|
|
262
|
+
} => expr_uses_document(iterable) || stmt_uses_document(body),
|
|
244
263
|
Statement::Switch {
|
|
245
264
|
expr,
|
|
246
265
|
cases,
|
|
@@ -854,7 +873,7 @@ pub fn resolve_project_from_stdin(
|
|
|
854
873
|
let from_dir = stdin_path.parent().unwrap_or_else(|| Path::new("."));
|
|
855
874
|
|
|
856
875
|
for stmt in &program.statements {
|
|
857
|
-
if let
|
|
876
|
+
if let Some(from) = stmt_module_dep(stmt) {
|
|
858
877
|
if is_native_import(from.as_ref()) {
|
|
859
878
|
continue;
|
|
860
879
|
}
|
|
@@ -883,6 +902,21 @@ pub fn resolve_project_from_stdin(
|
|
|
883
902
|
.collect())
|
|
884
903
|
}
|
|
885
904
|
|
|
905
|
+
/// #305 — the module path a statement depends on: an `import ... from "p"` or a re-export
|
|
906
|
+
/// `export ... from "p"`. Used by dependency discovery + cycle detection so a module reached ONLY
|
|
907
|
+
/// through a re-export is still loaded. None for non-module statements.
|
|
908
|
+
fn stmt_module_dep(stmt: &Statement) -> Option<&std::sync::Arc<str>> {
|
|
909
|
+
match stmt {
|
|
910
|
+
Statement::Import { from, .. } => Some(from),
|
|
911
|
+
Statement::Export { declaration, .. } => match declaration.as_ref() {
|
|
912
|
+
// A local named export (`export { a }`, from=None) has no module dependency.
|
|
913
|
+
ExportDeclaration::ReExport { from, .. } => from.as_ref(),
|
|
914
|
+
_ => None,
|
|
915
|
+
},
|
|
916
|
+
_ => None,
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
886
920
|
fn load_module_recursive(
|
|
887
921
|
module_path: &Path,
|
|
888
922
|
project_root: &Path,
|
|
@@ -907,7 +941,7 @@ fn load_module_recursive(
|
|
|
907
941
|
// Collect imports and load dependencies first (skip native imports)
|
|
908
942
|
let dir = canonical.parent().unwrap_or(Path::new("."));
|
|
909
943
|
for stmt in &program.statements {
|
|
910
|
-
if let
|
|
944
|
+
if let Some(from) = stmt_module_dep(stmt) {
|
|
911
945
|
if is_native_import(from.as_ref()) {
|
|
912
946
|
continue; // Native imports don't load files
|
|
913
947
|
}
|
|
@@ -937,10 +971,15 @@ fn load_module_recursive(
|
|
|
937
971
|
///
|
|
938
972
|
/// Scoped npm packages (`@scope/pkg`) are merged as Tish source unless imported via `tish:…`.
|
|
939
973
|
pub fn is_native_import(spec: &str) -> bool {
|
|
974
|
+
// A leading `node:` (node:fs, node:fs/promises) resolves the same as the bare form.
|
|
975
|
+
let spec = spec.strip_prefix("node:").unwrap_or(spec);
|
|
940
976
|
spec.starts_with("tish:")
|
|
941
977
|
|| spec.starts_with("cargo:")
|
|
942
978
|
|| spec.starts_with("ffi:")
|
|
943
|
-
|| matches!(
|
|
979
|
+
|| matches!(
|
|
980
|
+
spec,
|
|
981
|
+
"fs" | "fs/promises" | "http" | "timers" | "process" | "ws" | "tty"
|
|
982
|
+
)
|
|
944
983
|
}
|
|
945
984
|
|
|
946
985
|
/// True for `ffi:…` specs (portable C-ABI cdylib extensions, loadable on every backend). The
|
|
@@ -1113,7 +1152,7 @@ fn has_cycle_from(
|
|
|
1113
1152
|
visiting: &mut HashSet<usize>,
|
|
1114
1153
|
) -> Result<bool, String> {
|
|
1115
1154
|
for stmt in &program.statements {
|
|
1116
|
-
if let
|
|
1155
|
+
if let Some(from) = stmt_module_dep(stmt) {
|
|
1117
1156
|
if is_native_import(from.as_ref()) {
|
|
1118
1157
|
continue;
|
|
1119
1158
|
}
|
|
@@ -1146,6 +1185,11 @@ fn has_cycle_from(
|
|
|
1146
1185
|
pub struct MergedProgram {
|
|
1147
1186
|
pub program: Program,
|
|
1148
1187
|
pub statement_sources: Vec<PathBuf>,
|
|
1188
|
+
/// #295: the ENTRY module's exported `(local_name, exported_name)` pairs, excluding `default`
|
|
1189
|
+
/// (handled separately as `export default`). Merge unwraps exports into plain top-level
|
|
1190
|
+
/// declarations, so `--target js --format bundle` re-emits these as a trailing `export { … }` to
|
|
1191
|
+
/// produce a valid ES module. Sorted by local name for deterministic output.
|
|
1192
|
+
pub entry_exports: Vec<(String, String)>,
|
|
1149
1193
|
}
|
|
1150
1194
|
|
|
1151
1195
|
fn merge_push(
|
|
@@ -1374,7 +1418,11 @@ fn shadow_params(
|
|
|
1374
1418
|
}
|
|
1375
1419
|
|
|
1376
1420
|
/// Scope-aware statement rewriter for [`isolate_private_top_level_bindings`].
|
|
1377
|
-
|
|
1421
|
+
/// Scope-aware statement rewriter: rename declared bindings and their free references
|
|
1422
|
+
/// according to `active` (name → new Arc). Exposed `pub(crate)` so the #179 factory inliner
|
|
1423
|
+
/// (infer.rs) can reuse this exhaustive, resolution-tested renamer for alpha-renaming a
|
|
1424
|
+
/// spliced factory body instead of hand-rolling a completeness-sensitive walker.
|
|
1425
|
+
pub(crate) fn rewrite_stmt_scope(
|
|
1378
1426
|
stmt: &mut Statement,
|
|
1379
1427
|
active: &mut HashMap<String, Arc<str>>,
|
|
1380
1428
|
top_level: bool,
|
|
@@ -1447,6 +1495,12 @@ fn rewrite_stmt_scope(
|
|
|
1447
1495
|
iterable,
|
|
1448
1496
|
body,
|
|
1449
1497
|
..
|
|
1498
|
+
}
|
|
1499
|
+
| Statement::ForIn {
|
|
1500
|
+
name,
|
|
1501
|
+
object: iterable,
|
|
1502
|
+
body,
|
|
1503
|
+
..
|
|
1450
1504
|
} => {
|
|
1451
1505
|
rewrite_expr_scope(iterable, active);
|
|
1452
1506
|
let mut child = active.clone();
|
|
@@ -1522,6 +1576,9 @@ fn rewrite_stmt_scope(
|
|
|
1522
1576
|
// body can still reference module-private names that were renamed.
|
|
1523
1577
|
ExportDeclaration::Named(inner) => rewrite_stmt_scope(inner, active, top_level),
|
|
1524
1578
|
ExportDeclaration::Default(e) => rewrite_expr_scope(e, active),
|
|
1579
|
+
// #305: a re-export has no inner statement/expr to scope-rewrite; names are resolved by
|
|
1580
|
+
// the export-table merge against the dep's (already-rewritten) bindings.
|
|
1581
|
+
ExportDeclaration::ReExport { .. } => {}
|
|
1525
1582
|
},
|
|
1526
1583
|
Statement::Import { .. }
|
|
1527
1584
|
| Statement::TypeAlias { .. }
|
|
@@ -1533,7 +1590,8 @@ fn rewrite_stmt_scope(
|
|
|
1533
1590
|
/// Scope-aware expression rewriter: rename every free reference to a name in `active`.
|
|
1534
1591
|
/// Expressions never declare module-level bindings, so `active` is read-only here; arrow
|
|
1535
1592
|
/// functions clone it for their own (shadowed) parameter scope.
|
|
1536
|
-
|
|
1593
|
+
/// `pub(crate)` so the #179 factory inliner can rename a spliced return expression.
|
|
1594
|
+
pub(crate) fn rewrite_expr_scope(expr: &mut Expr, active: &HashMap<String, Arc<str>>) {
|
|
1537
1595
|
let rename = |name: &mut Arc<str>| {
|
|
1538
1596
|
if let Some(renamed) = active.get(name.as_ref()) {
|
|
1539
1597
|
*name = Arc::clone(renamed);
|
|
@@ -1674,6 +1732,14 @@ fn rewrite_expr_scope(expr: &mut Expr, active: &HashMap<String, Arc<str>>) {
|
|
|
1674
1732
|
/// Import statements are rewritten as bindings from already-emitted dep exports.
|
|
1675
1733
|
/// Export statements are unwrapped (the inner declaration is emitted).
|
|
1676
1734
|
pub fn merge_modules(mut modules: Vec<ResolvedModule>) -> Result<MergedProgram, String> {
|
|
1735
|
+
// #469: give the ENTRY module a Go/Rust/Swift-style `main` entry point. The entry is the last
|
|
1736
|
+
// module (post-order dependency load order), and this runs BEFORE private-binding isolation so the
|
|
1737
|
+
// synthetic `main()` call is renamed in lockstep with the `main` declaration if isolation renames
|
|
1738
|
+
// it. Every backend consumes the merged program, so this keeps interp/vm/native/js consistent.
|
|
1739
|
+
if let Some(entry) = modules.last_mut() {
|
|
1740
|
+
tishlang_ast::append_main_entry(&mut entry.program.statements);
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1677
1743
|
// #97: isolate module-private top-level bindings before they are flattened together.
|
|
1678
1744
|
isolate_private_top_level_bindings(&mut modules);
|
|
1679
1745
|
|
|
@@ -1701,6 +1767,57 @@ pub fn merge_modules(mut modules: Vec<ResolvedModule>) -> Result<MergedProgram,
|
|
|
1701
1767
|
let default_name = format!("__default_{}", idx);
|
|
1702
1768
|
module_exports[idx].insert("default".to_string(), default_name);
|
|
1703
1769
|
}
|
|
1770
|
+
// #305: re-export — map each re-exported name to the DEP's binding (the dep is
|
|
1771
|
+
// earlier in load order, so its export table is already built). `export *` copies
|
|
1772
|
+
// every dep export (without overriding an explicit one); `export { a as b }` maps
|
|
1773
|
+
// b -> dep's binding for a. Downstream imports then resolve straight to the dep.
|
|
1774
|
+
ExportDeclaration::ReExport {
|
|
1775
|
+
specifiers,
|
|
1776
|
+
all,
|
|
1777
|
+
from: Some(from),
|
|
1778
|
+
..
|
|
1779
|
+
} => {
|
|
1780
|
+
let dir = module.path.parent().unwrap_or_else(|| Path::new("."));
|
|
1781
|
+
let dep = resolve_import_path(from.as_ref(), dir, Path::new("."))
|
|
1782
|
+
.ok()
|
|
1783
|
+
.map(|p| p.canonicalize().unwrap_or(p))
|
|
1784
|
+
.and_then(|p| path_to_idx.get(&p).copied())
|
|
1785
|
+
.map(|dep_idx| module_exports[dep_idx].clone());
|
|
1786
|
+
if let Some(dep) = dep {
|
|
1787
|
+
if *all {
|
|
1788
|
+
for (k, v) in &dep {
|
|
1789
|
+
module_exports[idx]
|
|
1790
|
+
.entry(k.clone())
|
|
1791
|
+
.or_insert_with(|| v.clone());
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
for spec in specifiers {
|
|
1795
|
+
if let ImportSpecifier::Named { name, alias, .. } = spec {
|
|
1796
|
+
if let Some(binding) = dep.get(name.as_ref()) {
|
|
1797
|
+
let export_name =
|
|
1798
|
+
alias.as_deref().unwrap_or(name.as_ref()).to_string();
|
|
1799
|
+
module_exports[idx].insert(export_name, binding.clone());
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
// #415 local named export (`export { a, b as c }`, no `from`): each specifier
|
|
1806
|
+
// exports an already-declared LOCAL top-level binding, mapping export-name -> that
|
|
1807
|
+
// binding. (`isolate_private_top_level_bindings` keeps exported names un-renamed.)
|
|
1808
|
+
ExportDeclaration::ReExport {
|
|
1809
|
+
specifiers,
|
|
1810
|
+
from: None,
|
|
1811
|
+
..
|
|
1812
|
+
} => {
|
|
1813
|
+
for spec in specifiers {
|
|
1814
|
+
if let ImportSpecifier::Named { name, alias, .. } = spec {
|
|
1815
|
+
let export_name =
|
|
1816
|
+
alias.as_deref().unwrap_or(name.as_ref()).to_string();
|
|
1817
|
+
module_exports[idx].insert(export_name, name.to_string());
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1704
1821
|
}
|
|
1705
1822
|
}
|
|
1706
1823
|
}
|
|
@@ -1885,6 +2002,10 @@ pub fn merge_modules(mut modules: Vec<ResolvedModule>) -> Result<MergedProgram,
|
|
|
1885
2002
|
src_path.clone(),
|
|
1886
2003
|
);
|
|
1887
2004
|
}
|
|
2005
|
+
// #305: re-export emits no code — `module_exports` already maps the re-exported
|
|
2006
|
+
// names to the dep's bindings (in scope in the flattened bundle), so downstream
|
|
2007
|
+
// imports resolve directly. Nothing to push here.
|
|
2008
|
+
ExportDeclaration::ReExport { .. } => {}
|
|
1888
2009
|
},
|
|
1889
2010
|
_ => merge_push(
|
|
1890
2011
|
&mut statements,
|
|
@@ -1895,9 +2016,26 @@ pub fn merge_modules(mut modules: Vec<ResolvedModule>) -> Result<MergedProgram,
|
|
|
1895
2016
|
}
|
|
1896
2017
|
}
|
|
1897
2018
|
}
|
|
2019
|
+
// #295: capture the ENTRY module's exports (the entry is last — deps are emitted first). Merge
|
|
2020
|
+
// already built `module_exports[idx]` as exported_name -> local_binding; re-express as
|
|
2021
|
+
// (local, exported) for the JS bundle emitter, excluding `default` (emitted as `export default`).
|
|
2022
|
+
let entry_exports: Vec<(String, String)> = modules
|
|
2023
|
+
.len()
|
|
2024
|
+
.checked_sub(1)
|
|
2025
|
+
.map(|last| {
|
|
2026
|
+
let mut v: Vec<(String, String)> = module_exports[last]
|
|
2027
|
+
.iter()
|
|
2028
|
+
.filter(|(exported, _)| exported.as_str() != "default")
|
|
2029
|
+
.map(|(exported, local)| (local.clone(), exported.clone()))
|
|
2030
|
+
.collect();
|
|
2031
|
+
v.sort();
|
|
2032
|
+
v
|
|
2033
|
+
})
|
|
2034
|
+
.unwrap_or_default();
|
|
1898
2035
|
Ok(MergedProgram {
|
|
1899
2036
|
program: Program { statements },
|
|
1900
2037
|
statement_sources,
|
|
2038
|
+
entry_exports,
|
|
1901
2039
|
})
|
|
1902
2040
|
}
|
|
1903
2041
|
|