@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
|
@@ -14,6 +14,26 @@ fn next_id() -> u64 {
|
|
|
14
14
|
NEXT_ID.fetch_add(1, Ordering::SeqCst)
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/// Maximum number of LIVE (registered, not-yet-fired) timers per worker thread. A program that keeps
|
|
18
|
+
/// scheduling `setTimeout`/`setInterval` without them draining would otherwise grow the registry (and
|
|
19
|
+
/// its retained callbacks + closed-over data) without bound (#384). Past the cap a new timer is
|
|
20
|
+
/// dropped rather than registered. Override with `TISH_MAX_TIMERS`; default 100k — far above any real
|
|
21
|
+
/// timer workload, low enough to bound memory.
|
|
22
|
+
fn max_live_timers() -> usize {
|
|
23
|
+
// Read per call (timer registration is not a hot path, and the cap exists precisely to bound the
|
|
24
|
+
// pathological caller): keeps the limit overridable per test without a process-global cache.
|
|
25
|
+
std::env::var("TISH_MAX_TIMERS")
|
|
26
|
+
.ok()
|
|
27
|
+
.and_then(|v| v.parse().ok())
|
|
28
|
+
.filter(|&n| n > 0)
|
|
29
|
+
.unwrap_or(100_000)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
#[cfg(test)]
|
|
33
|
+
fn registry_len() -> usize {
|
|
34
|
+
REGISTRY.with(|r| r.borrow().len())
|
|
35
|
+
}
|
|
36
|
+
|
|
17
37
|
struct TimerEntry {
|
|
18
38
|
due: Instant,
|
|
19
39
|
callback: Value,
|
|
@@ -114,7 +134,12 @@ pub fn set_timeout(args: &[Value]) -> Value {
|
|
|
114
134
|
let id = next_id();
|
|
115
135
|
let due = Instant::now() + Duration::from_millis(delay_ms);
|
|
116
136
|
REGISTRY.with(|r| {
|
|
117
|
-
r.borrow_mut()
|
|
137
|
+
let mut reg = r.borrow_mut();
|
|
138
|
+
// #384: bound the live-timer count so a runaway scheduler can't grow the registry unbounded.
|
|
139
|
+
if reg.len() >= max_live_timers() {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
reg.insert(
|
|
118
143
|
id,
|
|
119
144
|
TimerEntry {
|
|
120
145
|
due,
|
|
@@ -138,7 +163,12 @@ pub fn set_interval(args: &[Value]) -> Value {
|
|
|
138
163
|
let id = next_id();
|
|
139
164
|
let due = Instant::now() + Duration::from_millis(interval_ms);
|
|
140
165
|
REGISTRY.with(|r| {
|
|
141
|
-
r.borrow_mut()
|
|
166
|
+
let mut reg = r.borrow_mut();
|
|
167
|
+
// #384: bound the live-timer count (see set_timeout).
|
|
168
|
+
if reg.len() >= max_live_timers() {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
reg.insert(
|
|
142
172
|
id,
|
|
143
173
|
TimerEntry {
|
|
144
174
|
due,
|
|
@@ -170,3 +200,20 @@ pub fn clear_timeout(args: &[Value]) -> Value {
|
|
|
170
200
|
pub fn clear_interval(args: &[Value]) -> Value {
|
|
171
201
|
clear_timeout(args)
|
|
172
202
|
}
|
|
203
|
+
|
|
204
|
+
#[cfg(test)]
|
|
205
|
+
mod timer_cap_tests_384 {
|
|
206
|
+
use super::*;
|
|
207
|
+
|
|
208
|
+
#[test]
|
|
209
|
+
fn set_timeout_is_bounded_by_max_timers() {
|
|
210
|
+
// Each `#[test]` runs on its own thread, so REGISTRY (thread_local) starts empty here.
|
|
211
|
+
std::env::set_var("TISH_MAX_TIMERS", "5");
|
|
212
|
+
let cb = tishlang_core::native_fn(|_| Value::Null);
|
|
213
|
+
for _ in 0..20 {
|
|
214
|
+
let _ = set_timeout(&[Value::Function(cb.clone()), Value::Number(10_000.0)]);
|
|
215
|
+
}
|
|
216
|
+
assert_eq!(registry_len(), 5, "live timers must be capped at TISH_MAX_TIMERS");
|
|
217
|
+
std::env::remove_var("TISH_MAX_TIMERS");
|
|
218
|
+
}
|
|
219
|
+
}
|
|
@@ -188,7 +188,12 @@ fn collect_fun_decl_names_stmt(stmt: &Statement, names: &mut HashSet<String>) {
|
|
|
188
188
|
}
|
|
189
189
|
collect_fun_decl_names_stmt(body, names);
|
|
190
190
|
}
|
|
191
|
-
Statement::ForOf { iterable, body, .. }
|
|
191
|
+
Statement::ForOf { iterable, body, .. }
|
|
192
|
+
| Statement::ForIn {
|
|
193
|
+
object: iterable,
|
|
194
|
+
body,
|
|
195
|
+
..
|
|
196
|
+
} => {
|
|
192
197
|
collect_fun_decl_names_expr(iterable, names);
|
|
193
198
|
collect_fun_decl_names_stmt(body, names);
|
|
194
199
|
}
|
|
@@ -240,6 +245,7 @@ fn collect_fun_decl_names_stmt(stmt: &Statement, names: &mut HashSet<String>) {
|
|
|
240
245
|
Statement::Export { declaration, .. } => match declaration.as_ref() {
|
|
241
246
|
ExportDeclaration::Named(inner) => collect_fun_decl_names_stmt(inner, names),
|
|
242
247
|
ExportDeclaration::Default(e) => collect_fun_decl_names_expr(e, names),
|
|
248
|
+
ExportDeclaration::ReExport { .. } => {}
|
|
243
249
|
},
|
|
244
250
|
Statement::Import { .. }
|
|
245
251
|
| Statement::Break { .. }
|
|
@@ -645,7 +651,12 @@ fn stmt_contains_jsx_fragment(stmt: &tishlang_ast::Statement) -> bool {
|
|
|
645
651
|
|| update.as_ref().is_some_and(expr_contains_jsx_fragment)
|
|
646
652
|
|| stmt_contains_jsx_fragment(body)
|
|
647
653
|
}
|
|
648
|
-
Statement::ForOf { iterable, body, .. }
|
|
654
|
+
Statement::ForOf { iterable, body, .. }
|
|
655
|
+
| Statement::ForIn {
|
|
656
|
+
object: iterable,
|
|
657
|
+
body,
|
|
658
|
+
..
|
|
659
|
+
} => {
|
|
649
660
|
expr_contains_jsx_fragment(iterable) || stmt_contains_jsx_fragment(body)
|
|
650
661
|
}
|
|
651
662
|
Statement::Switch {
|
|
@@ -682,6 +693,7 @@ fn stmt_contains_jsx_fragment(stmt: &tishlang_ast::Statement) -> bool {
|
|
|
682
693
|
Statement::Export { declaration, .. } => match declaration.as_ref() {
|
|
683
694
|
ExportDeclaration::Named(inner) => stmt_contains_jsx_fragment(inner),
|
|
684
695
|
ExportDeclaration::Default(e) => expr_contains_jsx_fragment(e),
|
|
696
|
+
ExportDeclaration::ReExport { .. } => false,
|
|
685
697
|
},
|
|
686
698
|
Statement::Import { .. }
|
|
687
699
|
| Statement::Break { .. }
|
|
@@ -825,7 +837,12 @@ fn stmt_contains_jsx(stmt: &tishlang_ast::Statement) -> bool {
|
|
|
825
837
|
|| update.as_ref().is_some_and(expr_contains_jsx)
|
|
826
838
|
|| stmt_contains_jsx(body)
|
|
827
839
|
}
|
|
828
|
-
Statement::ForOf { iterable, body, .. }
|
|
840
|
+
Statement::ForOf { iterable, body, .. }
|
|
841
|
+
| Statement::ForIn {
|
|
842
|
+
object: iterable,
|
|
843
|
+
body,
|
|
844
|
+
..
|
|
845
|
+
} => {
|
|
829
846
|
expr_contains_jsx(iterable) || stmt_contains_jsx(body)
|
|
830
847
|
}
|
|
831
848
|
Statement::Switch {
|
|
@@ -857,6 +874,7 @@ fn stmt_contains_jsx(stmt: &tishlang_ast::Statement) -> bool {
|
|
|
857
874
|
Statement::Export { declaration, .. } => match declaration.as_ref() {
|
|
858
875
|
ExportDeclaration::Named(inner) => stmt_contains_jsx(inner),
|
|
859
876
|
ExportDeclaration::Default(e) => expr_contains_jsx(e),
|
|
877
|
+
ExportDeclaration::ReExport { .. } => false,
|
|
860
878
|
},
|
|
861
879
|
Statement::Import { .. }
|
|
862
880
|
| Statement::Break { .. }
|