@tishlang/tish-format 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.
Files changed (88) hide show
  1. package/Cargo.toml +3 -0
  2. package/bin/tish-format +0 -0
  3. package/crates/js_to_tish/src/transform/expr.rs +12 -2
  4. package/crates/tish/tests/fixtures/fs_parity_callbacks.tish +22 -0
  5. package/crates/tish/tests/fixtures/fs_parity_promises.tish +21 -0
  6. package/crates/tish/tests/fixtures/fs_parity_sync.tish +20 -0
  7. package/crates/tish/tests/fs_parity.rs +103 -0
  8. package/crates/tish/tests/integration_test.rs +80 -0
  9. package/crates/tish/tests/shortcircuit.rs +3 -3
  10. package/crates/tish_ast/src/ast.rs +84 -0
  11. package/crates/tish_builtins/Cargo.toml +1 -0
  12. package/crates/tish_builtins/src/array.rs +724 -72
  13. package/crates/tish_builtins/src/collections.rs +149 -40
  14. package/crates/tish_builtins/src/globals.rs +215 -25
  15. package/crates/tish_builtins/src/math.rs +65 -7
  16. package/crates/tish_builtins/src/number.rs +173 -0
  17. package/crates/tish_builtins/src/string.rs +263 -23
  18. package/crates/tish_bytecode/src/chunk.rs +7 -0
  19. package/crates/tish_bytecode/src/compiler.rs +611 -63
  20. package/crates/tish_bytecode/src/lib.rs +1 -1
  21. package/crates/tish_bytecode/src/opcode.rs +156 -2
  22. package/crates/tish_bytecode/src/serialize.rs +2 -0
  23. package/crates/tish_bytecode/tests/append_local_string_builder.rs +63 -0
  24. package/crates/tish_bytecode/tests/math_unary_intrinsic.rs +47 -0
  25. package/crates/tish_compile/src/codegen.rs +18219 -5283
  26. package/crates/tish_compile/src/infer.rs +1562 -30
  27. package/crates/tish_compile/src/lib.rs +29 -4
  28. package/crates/tish_compile/src/resolve.rs +151 -13
  29. package/crates/tish_compile/src/types.rs +224 -28
  30. package/crates/tish_compile/tests/dump_codegen.rs +21 -0
  31. package/crates/tish_compile/tests/perf_codegen_169_173.rs +8 -17
  32. package/crates/tish_compile/tests/perf_codegen_173_part3.rs +61 -0
  33. package/crates/tish_compile/tests/perf_codegen_174.rs +160 -0
  34. package/crates/tish_compile/tests/perf_codegen_175.rs +190 -0
  35. package/crates/tish_compile/tests/perf_codegen_176.rs +60 -0
  36. package/crates/tish_compile/tests/perf_codegen_177.rs +167 -0
  37. package/crates/tish_compile/tests/perf_codegen_178.rs +114 -0
  38. package/crates/tish_compile/tests/perf_codegen_178_rec.rs +124 -0
  39. package/crates/tish_compile/tests/perf_codegen_181.rs +36 -0
  40. package/crates/tish_compile/tests/perf_codegen_320.rs +211 -0
  41. package/crates/tish_compile/tests/perf_codegen_module_const_forof.rs +40 -0
  42. package/crates/tish_compile_js/src/codegen.rs +94 -3
  43. package/crates/tish_compile_js/src/tests_jsx.rs +27 -0
  44. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +115 -2
  45. package/crates/tish_core/Cargo.toml +4 -0
  46. package/crates/tish_core/src/json.rs +109 -6
  47. package/crates/tish_core/src/lib.rs +222 -2
  48. package/crates/tish_core/src/shape.rs +4 -2
  49. package/crates/tish_core/src/uri.rs +45 -0
  50. package/crates/tish_core/src/value.rs +571 -35
  51. package/crates/tish_core/src/vmref.rs +14 -0
  52. package/crates/tish_eval/Cargo.toml +2 -1
  53. package/crates/tish_eval/src/eval.rs +1328 -101
  54. package/crates/tish_eval/src/natives.rs +283 -18
  55. package/crates/tish_eval/src/regex.rs +47 -1
  56. package/crates/tish_eval/src/value.rs +76 -21
  57. package/crates/tish_ffi/src/lib.rs +11 -1
  58. package/crates/tish_ffi/tests/double_free.rs +35 -0
  59. package/crates/tish_fmt/Cargo.toml +1 -1
  60. package/crates/tish_fmt/src/lib.rs +94 -1
  61. package/crates/tish_lexer/src/lib.rs +76 -0
  62. package/crates/tish_lexer/src/token.rs +4 -0
  63. package/crates/tish_lint/src/lib.rs +126 -0
  64. package/crates/tish_lsp/README.md +2 -1
  65. package/crates/tish_lsp/src/main.rs +378 -28
  66. package/crates/tish_native/src/build.rs +41 -0
  67. package/crates/tish_opt/src/lib.rs +20 -1
  68. package/crates/tish_parser/Cargo.toml +4 -0
  69. package/crates/tish_parser/src/lib.rs +68 -0
  70. package/crates/tish_parser/src/parser.rs +479 -28
  71. package/crates/tish_resolve/src/lib.rs +75 -5
  72. package/crates/tish_runtime/Cargo.toml +10 -1
  73. package/crates/tish_runtime/src/fs_ext.rs +359 -0
  74. package/crates/tish_runtime/src/http.rs +28 -10
  75. package/crates/tish_runtime/src/http_fetch.rs +150 -1
  76. package/crates/tish_runtime/src/http_hyper.rs +41 -18
  77. package/crates/tish_runtime/src/http_prefork.rs +72 -11
  78. package/crates/tish_runtime/src/lib.rs +651 -51
  79. package/crates/tish_runtime/src/timers.rs +49 -2
  80. package/crates/tish_ui/src/jsx.rs +21 -3
  81. package/crates/tish_vm/src/jit.rs +2514 -117
  82. package/crates/tish_vm/src/vm.rs +1479 -224
  83. package/package.json +1 -1
  84. package/platform/darwin-arm64/tish-fmt +0 -0
  85. package/platform/darwin-x64/tish-fmt +0 -0
  86. package/platform/linux-arm64/tish-fmt +0 -0
  87. package/platform/linux-x64/tish-fmt +0 -0
  88. package/platform/win32-x64/tish-fmt.exe +0 -0
@@ -118,6 +118,19 @@ fn optimize_statement(stmt: &Statement) -> Statement {
118
118
  body: Box::new(optimize_statement(body)),
119
119
  span: *span,
120
120
  },
121
+ Statement::ForIn {
122
+ name,
123
+ name_span,
124
+ object,
125
+ body,
126
+ span,
127
+ } => Statement::ForIn {
128
+ name: Arc::clone(name),
129
+ name_span: *name_span,
130
+ object: optimize_expr(object),
131
+ body: Box::new(optimize_statement(body)),
132
+ span: *span,
133
+ },
121
134
  Statement::Return { value, span } => Statement::Return {
122
135
  value: value.as_ref().map(optimize_expr),
123
136
  span: *span,
@@ -500,12 +513,18 @@ fn optimize_expr(expr: &Expr) -> Expr {
500
513
  value: Box::new(optimize_expr(value)),
501
514
  span: *span,
502
515
  },
503
- Expr::ArrowFunction { params, body, span } => {
516
+ Expr::ArrowFunction {
517
+ async_,
518
+ params,
519
+ body,
520
+ span,
521
+ } => {
504
522
  let opt_body = match body {
505
523
  ArrowBody::Expr(e) => ArrowBody::Expr(Box::new(optimize_expr(e))),
506
524
  ArrowBody::Block(s) => ArrowBody::Block(Box::new(optimize_statement(s))),
507
525
  };
508
526
  Expr::ArrowFunction {
527
+ async_: *async_,
509
528
  params: params.clone(),
510
529
  body: opt_body,
511
530
  span: *span,
@@ -9,3 +9,7 @@ repository = { workspace = true }
9
9
  [dependencies]
10
10
  tishlang_lexer = { path = "../tish_lexer", version = ">=0.1" }
11
11
  tishlang_ast = { path = "../tish_ast", version = ">=0.1" }
12
+ # #381: grow the stack on demand during the recursive descent so deeply-nested source can't overflow
13
+ # the fixed OS thread stack before the MAX_PARSE_DEPTH bound converts it into a catchable error.
14
+ # (No-op shim on wasm32, matching tish_eval / tish_vm.)
15
+ stacker = "0.1"
@@ -33,6 +33,74 @@ mod tests {
33
33
  use super::*;
34
34
  use tishlang_ast::{CallArg, Expr, ObjectProp, Statement};
35
35
 
36
+ /// #381: pathologically nested source must return a catchable `Err`, NOT overflow the native
37
+ /// stack and abort the process. Exercises expression nesting (`((((…`), array nesting (`[[[[…`),
38
+ /// and prefix-op nesting (`-!-!…`) — all funnel through the depth-guarded `parse_unary`.
39
+ #[test]
40
+ fn deeply_nested_source_errors_instead_of_aborting() {
41
+ let n = 50_000;
42
+ for (open, close) in [("(", ")"), ("[", "]")] {
43
+ let src = format!("let x = {}1{}", open.repeat(n), close.repeat(n));
44
+ let r = parse(&src);
45
+ assert!(r.is_err(), "{n}× nested {open} should be a catchable Err, not an abort");
46
+ assert!(
47
+ r.unwrap_err().contains("nesting too deep"),
48
+ "expected a depth-limit error"
49
+ );
50
+ }
51
+ let prefix = format!("let x = {}1", "-".repeat(n));
52
+ assert!(parse(&prefix).is_err(), "deep prefix-op chain should error, not abort");
53
+ }
54
+
55
+ /// The depth guard must not reject ordinary, modestly-nested code.
56
+ #[test]
57
+ fn normal_nesting_still_parses() {
58
+ assert!(parse("let x = ((((1 + 2))))").is_ok());
59
+ assert!(parse("let y = [[1, 2], [3, [4, [5]]]]").is_ok());
60
+ assert!(parse("fn f() { if (a) { if (b) { return 1 } } }").is_ok());
61
+ }
62
+
63
+ /// #244: loose equality `==` / `!=` is rejected uniformly at parse (across every backend), with an
64
+ /// actionable message pointing at the strict form. `===` / `!==` still parse.
65
+ #[test]
66
+ fn loose_equality_is_rejected_at_parse() {
67
+ let eq = parse("let b = 1 == 1").unwrap_err();
68
+ assert!(eq.contains("'=='") && eq.contains("'==='"), "got: {eq}");
69
+ let ne = parse("let b = 1 != 2").unwrap_err();
70
+ assert!(ne.contains("'!='") && ne.contains("'!=='"), "got: {ne}");
71
+ // Rejected wherever an expression is parsed, not just at top level.
72
+ assert!(parse("fn f(x) { if (x == 0) { return 1 } return 0 }").is_err());
73
+ assert!(parse("let y = a != null && a.b").is_err());
74
+ // Strict forms are unaffected.
75
+ assert!(parse("let b = 1 === 1").is_ok());
76
+ assert!(parse("let b = 1 !== 2").is_ok());
77
+ assert!(parse("let y = a !== null && a.b").is_ok());
78
+ }
79
+
80
+ /// #428: `async` in expression position parses as an async arrow (paren and single-param forms);
81
+ /// non-async arrows keep `async_: false`.
82
+ #[test]
83
+ fn async_arrow_expressions_parse() {
84
+ use tishlang_ast::Expr;
85
+ let arrow_async = |src: &str| -> bool {
86
+ let p = parse(src).expect("parse");
87
+ let Some(Statement::VarDecl { init: Some(e), .. }) = p.statements.first() else {
88
+ panic!("expected `let x = <arrow>`");
89
+ };
90
+ match e {
91
+ Expr::ArrowFunction { async_, .. } => *async_,
92
+ other => panic!("expected ArrowFunction, got {other:?}"),
93
+ }
94
+ };
95
+ assert!(arrow_async("let f = async () => 1"), "async paren arrow");
96
+ assert!(arrow_async("let g = async x => x + 1"), "async single-param arrow");
97
+ assert!(arrow_async("let h = async (a, b) => a + b"), "async multi-param arrow");
98
+ assert!(!arrow_async("let f = () => 1"), "plain arrow is not async");
99
+ assert!(!arrow_async("let g = x => x"), "plain single-param arrow is not async");
100
+ // `async` not followed by an arrow in expr position is an error, not a silent identifier.
101
+ assert!(parse("let x = async 5").is_err());
102
+ }
103
+
36
104
  #[test]
37
105
  fn test_async_fn_parse() {
38
106
  let program = parse("async fn foo() { }").expect("parse async fn");