@tishlang/tish 2.12.0 → 2.16.13
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 +0 -0
- package/crates/tish/Cargo.toml +1 -1
- package/crates/tish/tests/integration_test.rs +80 -0
- package/crates/tish_ast/src/ast.rs +10 -0
- package/crates/tish_builtins/src/array.rs +529 -56
- package/crates/tish_builtins/src/collections.rs +114 -40
- package/crates/tish_builtins/src/string.rs +95 -8
- package/crates/tish_bytecode/src/chunk.rs +7 -0
- package/crates/tish_bytecode/src/compiler.rs +560 -64
- package/crates/tish_bytecode/src/lib.rs +1 -1
- package/crates/tish_bytecode/src/opcode.rs +154 -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 +17736 -5269
- package/crates/tish_compile/src/infer.rs +1707 -190
- package/crates/tish_compile/src/lib.rs +29 -4
- package/crates/tish_compile/src/resolve.rs +66 -5
- 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 +33 -0
- package/crates/tish_compiler_wasm/src/resolve_virtual.rs +100 -2
- package/crates/tish_core/Cargo.toml +4 -0
- package/crates/tish_core/src/json.rs +104 -5
- package/crates/tish_core/src/lib.rs +174 -0
- package/crates/tish_core/src/shape.rs +4 -2
- package/crates/tish_core/src/value.rs +565 -35
- package/crates/tish_core/src/vmref.rs +14 -0
- package/crates/tish_eval/src/eval.rs +675 -76
- package/crates/tish_eval/src/natives.rs +19 -0
- 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 +75 -1
- package/crates/tish_lexer/src/lib.rs +76 -0
- package/crates/tish_lexer/src/token.rs +4 -0
- 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_parser/Cargo.toml +4 -0
- package/crates/tish_parser/src/lib.rs +27 -0
- package/crates/tish_parser/src/parser.rs +302 -20
- package/crates/tish_resolve/src/lib.rs +9 -0
- package/crates/tish_runtime/Cargo.toml +5 -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_prefork.rs +72 -11
- package/crates/tish_runtime/src/lib.rs +523 -42
- package/crates/tish_runtime/src/timers.rs +49 -2
- package/crates/tish_ui/src/jsx.rs +3 -0
- package/crates/tish_vm/src/jit.rs +2514 -117
- package/crates/tish_vm/src/vm.rs +1227 -182
- 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
|
@@ -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
|
+
}
|
|
@@ -240,6 +240,7 @@ fn collect_fun_decl_names_stmt(stmt: &Statement, names: &mut HashSet<String>) {
|
|
|
240
240
|
Statement::Export { declaration, .. } => match declaration.as_ref() {
|
|
241
241
|
ExportDeclaration::Named(inner) => collect_fun_decl_names_stmt(inner, names),
|
|
242
242
|
ExportDeclaration::Default(e) => collect_fun_decl_names_expr(e, names),
|
|
243
|
+
ExportDeclaration::ReExport { .. } => {}
|
|
243
244
|
},
|
|
244
245
|
Statement::Import { .. }
|
|
245
246
|
| Statement::Break { .. }
|
|
@@ -682,6 +683,7 @@ fn stmt_contains_jsx_fragment(stmt: &tishlang_ast::Statement) -> bool {
|
|
|
682
683
|
Statement::Export { declaration, .. } => match declaration.as_ref() {
|
|
683
684
|
ExportDeclaration::Named(inner) => stmt_contains_jsx_fragment(inner),
|
|
684
685
|
ExportDeclaration::Default(e) => expr_contains_jsx_fragment(e),
|
|
686
|
+
ExportDeclaration::ReExport { .. } => false,
|
|
685
687
|
},
|
|
686
688
|
Statement::Import { .. }
|
|
687
689
|
| Statement::Break { .. }
|
|
@@ -857,6 +859,7 @@ fn stmt_contains_jsx(stmt: &tishlang_ast::Statement) -> bool {
|
|
|
857
859
|
Statement::Export { declaration, .. } => match declaration.as_ref() {
|
|
858
860
|
ExportDeclaration::Named(inner) => stmt_contains_jsx(inner),
|
|
859
861
|
ExportDeclaration::Default(e) => expr_contains_jsx(e),
|
|
862
|
+
ExportDeclaration::ReExport { .. } => false,
|
|
860
863
|
},
|
|
861
864
|
Statement::Import { .. }
|
|
862
865
|
| Statement::Break { .. }
|