@tishlang/tish 1.5.0 → 1.7.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 (85) hide show
  1. package/Cargo.toml +1 -0
  2. package/bin/tish +0 -0
  3. package/crates/js_to_tish/src/error.rs +2 -8
  4. package/crates/js_to_tish/src/transform/expr.rs +101 -130
  5. package/crates/js_to_tish/src/transform/stmt.rs +25 -22
  6. package/crates/tish/Cargo.toml +1 -1
  7. package/crates/tish/src/cli_help.rs +76 -29
  8. package/crates/tish/src/main.rs +85 -54
  9. package/crates/tish/tests/cargo_example_compile.rs +67 -0
  10. package/crates/tish/tests/fixtures/cargo_example_project/Cargo.toml +3 -0
  11. package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/Cargo.toml +11 -0
  12. package/crates/tish/tests/fixtures/cargo_example_project/crates/demo-shim/src/lib.rs +12 -0
  13. package/crates/tish/tests/fixtures/cargo_example_project/package.json +10 -0
  14. package/crates/tish/tests/fixtures/cargo_example_project/src/main.tish +3 -0
  15. package/crates/tish/tests/integration_test.rs +197 -47
  16. package/crates/tish/tests/run_optimize_stdout_parity.rs +3 -7
  17. package/crates/tish/tests/shortcircuit.rs +19 -4
  18. package/crates/tish_ast/src/ast.rs +12 -14
  19. package/crates/tish_build_utils/src/lib.rs +64 -6
  20. package/crates/tish_builtins/src/array.rs +52 -21
  21. package/crates/tish_builtins/src/construct.rs +2 -8
  22. package/crates/tish_builtins/src/globals.rs +30 -15
  23. package/crates/tish_builtins/src/lib.rs +5 -5
  24. package/crates/tish_builtins/src/math.rs +5 -3
  25. package/crates/tish_builtins/src/string.rs +71 -19
  26. package/crates/tish_bytecode/src/chunk.rs +0 -1
  27. package/crates/tish_bytecode/src/compiler.rs +164 -60
  28. package/crates/tish_bytecode/src/opcode.rs +13 -4
  29. package/crates/tish_bytecode/src/peephole.rs +2 -2
  30. package/crates/tish_compile/Cargo.toml +1 -0
  31. package/crates/tish_compile/src/codegen.rs +989 -318
  32. package/crates/tish_compile/src/infer.rs +69 -19
  33. package/crates/tish_compile/src/lib.rs +21 -8
  34. package/crates/tish_compile/src/resolve.rs +515 -94
  35. package/crates/tish_compile/src/types.rs +10 -14
  36. package/crates/tish_compile_js/src/codegen.rs +34 -13
  37. package/crates/tish_compile_js/src/tests_jsx.rs +30 -6
  38. package/crates/tish_compiler_wasm/src/lib.rs +16 -13
  39. package/crates/tish_compiler_wasm/src/resolve_virtual.rs +40 -48
  40. package/crates/tish_core/src/json.rs +5 -3
  41. package/crates/tish_core/src/lib.rs +1 -1
  42. package/crates/tish_core/src/uri.rs +9 -6
  43. package/crates/tish_core/src/value.rs +92 -28
  44. package/crates/tish_cranelift/src/link.rs +6 -9
  45. package/crates/tish_cranelift/src/lower.rs +14 -8
  46. package/crates/tish_eval/src/eval.rs +398 -141
  47. package/crates/tish_eval/src/lib.rs +10 -6
  48. package/crates/tish_eval/src/natives.rs +95 -38
  49. package/crates/tish_eval/src/promise.rs +14 -8
  50. package/crates/tish_eval/src/timers.rs +28 -19
  51. package/crates/tish_eval/src/value.rs +10 -3
  52. package/crates/tish_fmt/src/lib.rs +29 -13
  53. package/crates/tish_lexer/src/lib.rs +217 -63
  54. package/crates/tish_lexer/src/token.rs +6 -6
  55. package/crates/tish_llvm/src/lib.rs +15 -8
  56. package/crates/tish_lsp/src/main.rs +41 -43
  57. package/crates/tish_native/src/build.rs +38 -15
  58. package/crates/tish_native/src/lib.rs +76 -32
  59. package/crates/tish_opt/src/lib.rs +67 -50
  60. package/crates/tish_parser/src/lib.rs +36 -11
  61. package/crates/tish_parser/src/parser.rs +172 -87
  62. package/crates/tish_runtime/src/http.rs +15 -6
  63. package/crates/tish_runtime/src/http_fetch.rs +24 -14
  64. package/crates/tish_runtime/src/lib.rs +224 -168
  65. package/crates/tish_runtime/src/promise.rs +1 -5
  66. package/crates/tish_runtime/src/ws.rs +45 -20
  67. package/crates/tish_runtime/tests/fetch_readable_stream.rs +5 -4
  68. package/crates/tish_ui/src/jsx.rs +41 -22
  69. package/crates/tish_ui/src/lib.rs +2 -2
  70. package/crates/tish_vm/src/vm.rs +320 -116
  71. package/crates/tish_vm/tests/peephole_jump_chain_logical_or.rs +8 -3
  72. package/crates/tish_wasm/src/lib.rs +38 -28
  73. package/crates/tishlang_cargo_bindgen/Cargo.toml +25 -0
  74. package/crates/tishlang_cargo_bindgen/src/classify.rs +265 -0
  75. package/crates/tishlang_cargo_bindgen/src/discover.rs +52 -0
  76. package/crates/tishlang_cargo_bindgen/src/infer.rs +372 -0
  77. package/crates/tishlang_cargo_bindgen/src/lib.rs +349 -0
  78. package/crates/tishlang_cargo_bindgen/src/main.rs +164 -0
  79. package/crates/tishlang_cargo_bindgen/src/metadata.rs +114 -0
  80. package/package.json +1 -1
  81. package/platform/darwin-arm64/tish +0 -0
  82. package/platform/darwin-x64/tish +0 -0
  83. package/platform/linux-arm64/tish +0 -0
  84. package/platform/linux-x64/tish +0 -0
  85. package/platform/win32-x64/tish.exe +0 -0
@@ -8,11 +8,14 @@ use std::path::{Path, PathBuf};
8
8
  use std::rc::Rc;
9
9
  use std::sync::Arc;
10
10
 
11
- use tishlang_ast::{BinOp, CompoundOp, ExportDeclaration, Expr, FunParam, ImportSpecifier, Literal, LogicalAssignOp, MemberProp, Span, Statement, UnaryOp};
11
+ use tishlang_ast::{
12
+ BinOp, CompoundOp, ExportDeclaration, Expr, FunParam, ImportSpecifier, Literal,
13
+ LogicalAssignOp, MemberProp, Span, Statement, UnaryOp,
14
+ };
12
15
 
13
- use crate::value::{PropMap, Value};
14
16
  #[cfg(any(feature = "fs", feature = "process"))]
15
17
  use crate::natives;
18
+ use crate::value::{PropMap, Value};
16
19
 
17
20
  struct Scope {
18
21
  vars: PropMap,
@@ -93,12 +96,24 @@ impl Evaluator {
93
96
  console.insert("log".into(), Value::Native(natives::console_log));
94
97
  console.insert("warn".into(), Value::Native(natives::console_warn));
95
98
  console.insert("error".into(), Value::Native(natives::console_error));
96
- s.set("console".into(), Value::Object(Rc::new(RefCell::new(console))), true);
99
+ s.set(
100
+ "console".into(),
101
+ Value::Object(Rc::new(RefCell::new(console))),
102
+ true,
103
+ );
97
104
  s.set("parseInt".into(), Value::Native(natives::parse_int), true);
98
- s.set("parseFloat".into(), Value::Native(natives::parse_float), true);
105
+ s.set(
106
+ "parseFloat".into(),
107
+ Value::Native(natives::parse_float),
108
+ true,
109
+ );
99
110
  s.set("decodeURI".into(), Value::Native(natives::decode_uri), true);
100
111
  s.set("encodeURI".into(), Value::Native(natives::encode_uri), true);
101
- s.set("Boolean".into(), Value::Native(natives::boolean_native), true);
112
+ s.set(
113
+ "Boolean".into(),
114
+ Value::Native(natives::boolean_native),
115
+ true,
116
+ );
102
117
  s.set("isFinite".into(), Value::Native(natives::is_finite), true);
103
118
  s.set("isNaN".into(), Value::Native(natives::is_nan), true);
104
119
  s.set("Infinity".into(), Value::Number(f64::INFINITY), true);
@@ -122,32 +137,65 @@ impl Evaluator {
122
137
  math.insert("trunc".into(), Value::Native(natives::math_trunc));
123
138
  math.insert("PI".into(), Value::Number(std::f64::consts::PI));
124
139
  math.insert("E".into(), Value::Number(std::f64::consts::E));
125
- s.set("Math".into(), Value::Object(Rc::new(RefCell::new(math))), true);
140
+ s.set(
141
+ "Math".into(),
142
+ Value::Object(Rc::new(RefCell::new(math))),
143
+ true,
144
+ );
126
145
 
127
146
  let mut json = PropMap::with_capacity(2);
128
147
  json.insert("parse".into(), Value::Native(Self::json_parse_native));
129
- json.insert("stringify".into(), Value::Native(Self::json_stringify_native));
130
- s.set("JSON".into(), Value::Object(Rc::new(RefCell::new(json))), true);
148
+ json.insert(
149
+ "stringify".into(),
150
+ Value::Native(Self::json_stringify_native),
151
+ );
152
+ s.set(
153
+ "JSON".into(),
154
+ Value::Object(Rc::new(RefCell::new(json))),
155
+ true,
156
+ );
131
157
 
132
158
  let mut object = PropMap::with_capacity(5);
133
159
  object.insert("keys".into(), Value::Native(Self::object_keys));
134
160
  object.insert("values".into(), Value::Native(Self::object_values));
135
161
  object.insert("entries".into(), Value::Native(Self::object_entries));
136
162
  object.insert("assign".into(), Value::Native(Self::object_assign));
137
- object.insert("fromEntries".into(), Value::Native(Self::object_from_entries));
138
- s.set("Object".into(), Value::Object(Rc::new(RefCell::new(object))), true);
163
+ object.insert(
164
+ "fromEntries".into(),
165
+ Value::Native(Self::object_from_entries),
166
+ );
167
+ s.set(
168
+ "Object".into(),
169
+ Value::Object(Rc::new(RefCell::new(object))),
170
+ true,
171
+ );
139
172
 
140
173
  let mut array_obj = PropMap::with_capacity(1);
141
174
  array_obj.insert("isArray".into(), Value::Native(natives::array_is_array));
142
- s.set("Array".into(), Value::Object(Rc::new(RefCell::new(array_obj))), true);
175
+ s.set(
176
+ "Array".into(),
177
+ Value::Object(Rc::new(RefCell::new(array_obj))),
178
+ true,
179
+ );
143
180
 
144
181
  let mut string_obj = PropMap::with_capacity(1);
145
- string_obj.insert("fromCharCode".into(), Value::Native(natives::string_from_char_code));
146
- s.set("String".into(), Value::Object(Rc::new(RefCell::new(string_obj))), true);
182
+ string_obj.insert(
183
+ "fromCharCode".into(),
184
+ Value::Native(natives::string_from_char_code),
185
+ );
186
+ s.set(
187
+ "String".into(),
188
+ Value::Object(Rc::new(RefCell::new(string_obj))),
189
+ true,
190
+ );
147
191
 
148
192
  let mut date = PropMap::with_capacity(1);
149
193
  date.insert("now".into(), Value::Native(natives::date_now));
150
- s.set("Date".into(), Value::Object(Rc::new(RefCell::new(date))), true);
194
+ s.set(
195
+ "Date".into(),
196
+ Value::Object(Rc::new(RefCell::new(date))),
197
+ true,
198
+ );
151
199
 
152
200
  s.set(
153
201
  "Uint8Array".into(),
@@ -166,7 +214,11 @@ impl Evaluator {
166
214
 
167
215
  #[cfg(feature = "regex")]
168
216
  {
169
- s.set("RegExp".into(), Value::Native(Self::regexp_constructor_native), true);
217
+ s.set(
218
+ "RegExp".into(),
219
+ Value::Native(Self::regexp_constructor_native),
220
+ true,
221
+ );
170
222
  }
171
223
 
172
224
  // fs, http, process: use import { x } from 'tish:fs' etc. No globals.
@@ -225,16 +277,28 @@ impl Evaluator {
225
277
  self.scope = prev;
226
278
  Ok(last)
227
279
  }
228
- Statement::VarDecl { name, mutable, init, .. } => {
280
+ Statement::VarDecl {
281
+ name,
282
+ mutable,
283
+ init,
284
+ ..
285
+ } => {
229
286
  let value = init
230
287
  .as_ref()
231
288
  .map(|e| self.eval_expr(e))
232
289
  .transpose()?
233
290
  .unwrap_or(Value::Null);
234
- self.scope.borrow_mut().set(Arc::clone(name), value, *mutable);
291
+ self.scope
292
+ .borrow_mut()
293
+ .set(Arc::clone(name), value, *mutable);
235
294
  Ok(Value::Null)
236
295
  }
237
- Statement::VarDeclDestructure { pattern, mutable, init, .. } => {
296
+ Statement::VarDeclDestructure {
297
+ pattern,
298
+ mutable,
299
+ init,
300
+ ..
301
+ } => {
238
302
  let value = self.eval_expr(init)?;
239
303
  self.bind_destruct_pattern(pattern, &value, *mutable)?;
240
304
  Ok(Value::Null)
@@ -269,15 +333,21 @@ impl Evaluator {
269
333
  }
270
334
  Ok(Value::Null)
271
335
  }
272
- Statement::ForOf { name, iterable, body, .. } => {
336
+ Statement::ForOf {
337
+ name,
338
+ iterable,
339
+ body,
340
+ ..
341
+ } => {
273
342
  let iter_val = self.eval_expr(iterable)?;
274
343
  let elements = match &iter_val {
275
- crate::value::Value::Array(arr) => arr.borrow().iter().cloned().collect::<Vec<_>>(),
276
- crate::value::Value::String(s) => {
277
- s.chars()
278
- .map(|c| crate::value::Value::String(Arc::from(c.to_string())))
279
- .collect::<Vec<_>>()
344
+ crate::value::Value::Array(arr) => {
345
+ arr.borrow().iter().cloned().collect::<Vec<_>>()
280
346
  }
347
+ crate::value::Value::String(s) => s
348
+ .chars()
349
+ .map(|c| crate::value::Value::String(Arc::from(c.to_string())))
350
+ .collect::<Vec<_>>(),
281
351
  _ => {
282
352
  return Err(EvalError::Error(format!(
283
353
  "for-of requires iterable (array or string), got {}",
@@ -360,7 +430,12 @@ impl Evaluator {
360
430
  self.scope.borrow_mut().set(Arc::clone(name), func, true);
361
431
  Ok(Value::Null)
362
432
  }
363
- Statement::Switch { expr, cases, default_body, .. } => {
433
+ Statement::Switch {
434
+ expr,
435
+ cases,
436
+ default_body,
437
+ ..
438
+ } => {
364
439
  let v = self.eval_expr(expr)?;
365
440
  let mut matched = false;
366
441
  for (case_expr, body) in cases {
@@ -438,7 +513,7 @@ impl Evaluator {
438
513
  ..
439
514
  } => {
440
515
  let try_result = self.eval_statement(body);
441
-
516
+
442
517
  let result = match try_result {
443
518
  Ok(v) => Ok(v),
444
519
  Err(EvalError::Throw(thrown)) => {
@@ -459,18 +534,24 @@ impl Evaluator {
459
534
  }
460
535
  Err(e) => Err(e),
461
536
  };
462
-
537
+
463
538
  if let Some(finally_stmt) = finally_body {
464
539
  let _ = self.eval_statement(finally_stmt);
465
540
  }
466
-
541
+
467
542
  result
468
543
  }
469
- Statement::Import { specifiers, from, .. } => {
544
+ Statement::Import {
545
+ specifiers, from, ..
546
+ } => {
470
547
  let exports_val = self.load_module(from)?;
471
548
  let exports = match &exports_val {
472
549
  Value::Object(m) => m.borrow().clone(),
473
- _ => return Err(EvalError::Error("Module exports must be object".to_string())),
550
+ _ => {
551
+ return Err(EvalError::Error(
552
+ "Module exports must be object".to_string(),
553
+ ))
554
+ }
474
555
  };
475
556
  let mut scope = self.scope.borrow_mut();
476
557
  for spec in specifiers {
@@ -512,6 +593,12 @@ impl Evaluator {
512
593
 
513
594
  /// Load and evaluate a module, returning its exports object. Uses cache.
514
595
  fn load_module(&mut self, from: &str) -> Result<Value, EvalError> {
596
+ if from.starts_with("cargo:") {
597
+ return Err(EvalError::Error(
598
+ "cargo:… imports are only supported by `tish build` with the Rust native backend."
599
+ .into(),
600
+ ));
601
+ }
515
602
  if from.starts_with("tish:") {
516
603
  return self.load_builtin_module(from);
517
604
  }
@@ -520,24 +607,24 @@ impl Evaluator {
520
607
  return self.load_builtin_module(from);
521
608
  }
522
609
  let dir = self.current_dir.borrow().clone().ok_or_else(|| {
523
- EvalError::Error("Cannot resolve imports: no current file directory (use run_file)".to_string())
610
+ EvalError::Error(
611
+ "Cannot resolve imports: no current file directory (use run_file)".to_string(),
612
+ )
524
613
  })?;
525
614
  let path = Self::resolve_import_path(from, &dir)?;
526
- let path = path.canonicalize().map_err(|e| {
527
- EvalError::Error(format!("Cannot resolve import '{}': {}", from, e))
528
- })?;
615
+ let path = path
616
+ .canonicalize()
617
+ .map_err(|e| EvalError::Error(format!("Cannot resolve import '{}': {}", from, e)))?;
529
618
  {
530
619
  let cache = self.module_cache.borrow();
531
620
  if let Some(m) = cache.get(&path) {
532
621
  return Ok(m.clone());
533
622
  }
534
623
  }
535
- let source = std::fs::read_to_string(&path).map_err(|e| {
536
- EvalError::Error(format!("Cannot read {}: {}", path.display(), e))
537
- })?;
538
- let program = tishlang_parser::parse(&source).map_err(|e| {
539
- EvalError::Error(format!("Parse error in {}: {}", path.display(), e))
540
- })?;
624
+ let source = std::fs::read_to_string(&path)
625
+ .map_err(|e| EvalError::Error(format!("Cannot read {}: {}", path.display(), e)))?;
626
+ let program = tishlang_parser::parse(&source)
627
+ .map_err(|e| EvalError::Error(format!("Parse error in {}: {}", path.display(), e)))?;
541
628
  let module_scope = Scope::child(Rc::clone(&self.scope));
542
629
  let prev_scope = std::mem::replace(&mut self.scope, Rc::clone(&module_scope));
543
630
  let parent_dir = self.current_dir.borrow().clone();
@@ -549,7 +636,9 @@ impl Evaluator {
549
636
  match declaration.as_ref() {
550
637
  ExportDeclaration::Named(s) => {
551
638
  let _ = self.eval_statement(s);
552
- if let Statement::VarDecl { name, .. } | Statement::FunDecl { name, .. } = s.as_ref() {
639
+ if let Statement::VarDecl { name, .. } | Statement::FunDecl { name, .. } =
640
+ s.as_ref()
641
+ {
553
642
  export_names.push(name.to_string());
554
643
  }
555
644
  }
@@ -572,7 +661,9 @@ impl Evaluator {
572
661
  *self.current_dir.borrow_mut() = parent_dir;
573
662
  self.scope = prev_scope;
574
663
  let exports_val = Value::Object(Rc::new(RefCell::new(exports)));
575
- self.module_cache.borrow_mut().insert(path, exports_val.clone());
664
+ self.module_cache
665
+ .borrow_mut()
666
+ .insert(path, exports_val.clone());
576
667
  Ok(exports_val)
577
668
  }
578
669
 
@@ -599,6 +690,11 @@ impl Evaluator {
599
690
 
600
691
  /// Load built-in module (tish:fs, tish:http, tish:process, …) or a virtual module from native crates.
601
692
  fn load_builtin_module(&self, spec: &str) -> Result<Value, EvalError> {
693
+ if spec.starts_with("cargo:") {
694
+ return Err(EvalError::Error(
695
+ "cargo:… imports are only supported when compiling with `tish build` and the Rust native backend. They link Cargo crates via package.json tish.rustDependencies and a generated native wrapper — not the interpreter or VM.".into(),
696
+ ));
697
+ }
602
698
  if let Some(v) = self.virtual_builtins.borrow().get(spec) {
603
699
  return Ok(v.clone());
604
700
  }
@@ -630,10 +726,22 @@ impl Evaluator {
630
726
  exports.insert("fetchAll".into(), Value::Native(Self::fetch_all_native));
631
727
  exports.insert("serve".into(), Value::Serve);
632
728
  exports.insert("Promise".into(), Value::PromiseConstructor);
633
- exports.insert("setTimeout".into(), Value::TimerBuiltin(Arc::from("setTimeout")));
634
- exports.insert("setInterval".into(), Value::TimerBuiltin(Arc::from("setInterval")));
635
- exports.insert("clearTimeout".into(), Value::Native(Self::clear_timeout_native));
636
- exports.insert("clearInterval".into(), Value::Native(Self::clear_interval_native));
729
+ exports.insert(
730
+ "setTimeout".into(),
731
+ Value::TimerBuiltin(Arc::from("setTimeout")),
732
+ );
733
+ exports.insert(
734
+ "setInterval".into(),
735
+ Value::TimerBuiltin(Arc::from("setInterval")),
736
+ );
737
+ exports.insert(
738
+ "clearTimeout".into(),
739
+ Value::Native(Self::clear_timeout_native),
740
+ );
741
+ exports.insert(
742
+ "clearInterval".into(),
743
+ Value::Native(Self::clear_interval_native),
744
+ );
637
745
  return Ok(Value::Object(Rc::new(RefCell::new(exports))));
638
746
  }
639
747
  #[cfg(not(feature = "http"))]
@@ -647,10 +755,16 @@ impl Evaluator {
647
755
  #[cfg(feature = "ws")]
648
756
  {
649
757
  let mut exports: PropMap = PropMap::default();
650
- exports.insert("WebSocket".into(), Value::Native(Self::ws_web_socket_native));
758
+ exports.insert(
759
+ "WebSocket".into(),
760
+ Value::Native(Self::ws_web_socket_native),
761
+ );
651
762
  exports.insert("Server".into(), Value::Native(Self::ws_server_native));
652
763
  exports.insert("wsSend".into(), Value::Native(Self::ws_send_native));
653
- exports.insert("wsBroadcast".into(), Value::Native(Self::ws_broadcast_native));
764
+ exports.insert(
765
+ "wsBroadcast".into(),
766
+ Value::Native(Self::ws_broadcast_native),
767
+ );
654
768
  return Ok(Value::Object(Rc::new(RefCell::new(exports))));
655
769
  }
656
770
  #[cfg(not(feature = "ws"))]
@@ -667,21 +781,29 @@ impl Evaluator {
667
781
  exports.insert("exit".into(), Value::Native(natives::process_exit));
668
782
  exports.insert("cwd".into(), Value::Native(natives::process_cwd));
669
783
  exports.insert("exec".into(), Value::Native(natives::process_exec));
670
- let argv: Vec<Value> = std::env::args()
671
- .map(|s| Value::String(s.into()))
672
- .collect();
673
- exports.insert("argv".into(), Value::Array(Rc::new(RefCell::new(argv.clone()))));
784
+ let argv: Vec<Value> =
785
+ std::env::args().map(|s| Value::String(s.into())).collect();
786
+ exports.insert(
787
+ "argv".into(),
788
+ Value::Array(Rc::new(RefCell::new(argv.clone()))),
789
+ );
674
790
  let env_obj: PropMap = std::env::vars()
675
791
  .map(|(key, value)| (Arc::from(key.as_str()), Value::String(value.into())))
676
792
  .collect();
677
- exports.insert("env".into(), Value::Object(Rc::new(RefCell::new(env_obj.clone()))));
793
+ exports.insert(
794
+ "env".into(),
795
+ Value::Object(Rc::new(RefCell::new(env_obj.clone()))),
796
+ );
678
797
  let mut process_obj = PropMap::default();
679
798
  process_obj.insert("exit".into(), Value::Native(natives::process_exit));
680
799
  process_obj.insert("cwd".into(), Value::Native(natives::process_cwd));
681
800
  process_obj.insert("exec".into(), Value::Native(natives::process_exec));
682
801
  process_obj.insert("argv".into(), Value::Array(Rc::new(RefCell::new(argv))));
683
802
  process_obj.insert("env".into(), Value::Object(Rc::new(RefCell::new(env_obj))));
684
- exports.insert("process".into(), Value::Object(Rc::new(RefCell::new(process_obj))));
803
+ exports.insert(
804
+ "process".into(),
805
+ Value::Object(Rc::new(RefCell::new(process_obj))),
806
+ );
685
807
  return Ok(Value::Object(Rc::new(RefCell::new(exports))));
686
808
  }
687
809
  #[cfg(not(feature = "process"))]
@@ -1902,7 +2024,13 @@ impl Evaluator {
1902
2024
  /// descending = false: checks for `(a, b) => a - b`
1903
2025
  /// descending = true: checks for `(a, b) => b - a`
1904
2026
  fn is_numeric_sort_comparator(f: &Value, descending: bool) -> bool {
1905
- if let Value::Function { formals, body, rest_param, .. } = f {
2027
+ if let Value::Function {
2028
+ formals,
2029
+ body,
2030
+ rest_param,
2031
+ ..
2032
+ } = f
2033
+ {
1906
2034
  // Must have exactly 2 simple params, no defaults, no rest
1907
2035
  if formals.len() != 2 || rest_param.is_some() {
1908
2036
  return false;
@@ -1926,15 +2054,29 @@ impl Evaluator {
1926
2054
  };
1927
2055
 
1928
2056
  // Check for binary subtraction
1929
- if let Expr::Binary { left, op: BinOp::Sub, right, .. } = expr {
2057
+ if let Expr::Binary {
2058
+ left,
2059
+ op: BinOp::Sub,
2060
+ right,
2061
+ ..
2062
+ } = expr
2063
+ {
1930
2064
  // Check left is Ident(a) and right is Ident(b)
1931
2065
  let (expected_left, expected_right) = if descending {
1932
- (param_b, param_a) // b - a
2066
+ (param_b, param_a) // b - a
1933
2067
  } else {
1934
- (param_a, param_b) // a - b
2068
+ (param_a, param_b) // a - b
1935
2069
  };
1936
2070
 
1937
- if let (Expr::Ident { name: left_name, .. }, Expr::Ident { name: right_name, .. }) = (left.as_ref(), right.as_ref()) {
2071
+ if let (
2072
+ Expr::Ident {
2073
+ name: left_name, ..
2074
+ },
2075
+ Expr::Ident {
2076
+ name: right_name, ..
2077
+ },
2078
+ ) = (left.as_ref(), right.as_ref())
2079
+ {
1938
2080
  return left_name == expected_left && right_name == expected_right;
1939
2081
  }
1940
2082
  }
@@ -1989,8 +2131,17 @@ impl Evaluator {
1989
2131
 
1990
2132
  /// Optimized callback invocation for array methods.
1991
2133
  /// Creates a reusable scope that can be updated for each iteration.
1992
- fn create_callback_scope(&self, f: &Value) -> Option<(Rc<RefCell<Scope>>, Arc<[Arc<str>]>, Arc<Statement>)> {
1993
- if let Value::Function { formals, body, rest_param, .. } = f {
2134
+ fn create_callback_scope(
2135
+ &self,
2136
+ f: &Value,
2137
+ ) -> Option<(Rc<RefCell<Scope>>, Arc<[Arc<str>]>, Arc<Statement>)> {
2138
+ if let Value::Function {
2139
+ formals,
2140
+ body,
2141
+ rest_param,
2142
+ ..
2143
+ } = f
2144
+ {
1994
2145
  if rest_param.is_some() {
1995
2146
  return None;
1996
2147
  }
@@ -2053,12 +2204,14 @@ impl Evaluator {
2053
2204
 
2054
2205
  /// Try to evaluate a simple callback expression directly without creating a scope.
2055
2206
  /// Returns Some(result) for simple patterns like `x => x * 2` or `x => x > 5`.
2056
- fn eval_simple_callback(
2057
- &self,
2058
- f: &Value,
2059
- args: &[Value],
2060
- ) -> Option<Result<Value, EvalError>> {
2061
- if let Value::Function { formals, body, rest_param, .. } = f {
2207
+ fn eval_simple_callback(&self, f: &Value, args: &[Value]) -> Option<Result<Value, EvalError>> {
2208
+ if let Value::Function {
2209
+ formals,
2210
+ body,
2211
+ rest_param,
2212
+ ..
2213
+ } = f
2214
+ {
2062
2215
  if formals.len() != 1 || rest_param.is_some() {
2063
2216
  return None;
2064
2217
  }
@@ -2078,17 +2231,25 @@ impl Evaluator {
2078
2231
  // Fast path for common patterns
2079
2232
  match expr {
2080
2233
  // x * constant or x + constant, etc.
2081
- Expr::Binary { left, op, right, .. } => {
2234
+ Expr::Binary {
2235
+ left, op, right, ..
2236
+ } => {
2082
2237
  let left_val = self.eval_simple_operand(left, param_name, &arg)?;
2083
2238
  let right_val = self.eval_simple_operand(right, param_name, &arg)?;
2084
- Some(self.eval_binop(&left_val, *op, &right_val).map_err(EvalError::Error))
2239
+ Some(
2240
+ self.eval_binop(&left_val, *op, &right_val)
2241
+ .map_err(EvalError::Error),
2242
+ )
2085
2243
  }
2086
2244
  // Just return the parameter
2087
- Expr::Ident { name, .. } if name == param_name => {
2088
- Some(Ok(arg))
2089
- }
2245
+ Expr::Ident { name, .. } if name == param_name => Some(Ok(arg)),
2090
2246
  // Property access: x.prop
2091
- Expr::Member { object, prop, optional, .. } => {
2247
+ Expr::Member {
2248
+ object,
2249
+ prop,
2250
+ optional,
2251
+ ..
2252
+ } => {
2092
2253
  if let Expr::Ident { name, .. } = object.as_ref() {
2093
2254
  if name == param_name {
2094
2255
  return self.eval_simple_member(&arg, prop, *optional);
@@ -2104,7 +2265,12 @@ impl Evaluator {
2104
2265
  }
2105
2266
 
2106
2267
  /// Evaluate a simple operand (identifier or literal).
2107
- fn eval_simple_operand(&self, expr: &Expr, param_name: &Arc<str>, param_val: &Value) -> Option<Value> {
2268
+ fn eval_simple_operand(
2269
+ &self,
2270
+ expr: &Expr,
2271
+ param_name: &Arc<str>,
2272
+ param_val: &Value,
2273
+ ) -> Option<Value> {
2108
2274
  match expr {
2109
2275
  Expr::Ident { name, .. } if name == param_name => Some(param_val.clone()),
2110
2276
  Expr::Literal { value, .. } => match value {
@@ -2118,20 +2284,27 @@ impl Evaluator {
2118
2284
  }
2119
2285
 
2120
2286
  /// Evaluate simple member access.
2121
- fn eval_simple_member(&self, obj: &Value, property: &MemberProp, _optional: bool) -> Option<Result<Value, EvalError>> {
2287
+ fn eval_simple_member(
2288
+ &self,
2289
+ obj: &Value,
2290
+ property: &MemberProp,
2291
+ _optional: bool,
2292
+ ) -> Option<Result<Value, EvalError>> {
2122
2293
  match property {
2123
- MemberProp::Name(name) => {
2124
- match obj {
2125
- Value::Object(o) => {
2126
- let result = o.borrow().get(name.as_ref()).cloned().unwrap_or(Value::Null);
2127
- Some(Ok(result))
2128
- }
2129
- Value::Array(arr) if name.as_ref() == "length" => {
2130
- Some(Ok(Value::Number(arr.borrow().len() as f64)))
2131
- }
2132
- _ => None,
2294
+ MemberProp::Name(name) => match obj {
2295
+ Value::Object(o) => {
2296
+ let result = o
2297
+ .borrow()
2298
+ .get(name.as_ref())
2299
+ .cloned()
2300
+ .unwrap_or(Value::Null);
2301
+ Some(Ok(result))
2302
+ }
2303
+ Value::Array(arr) if name.as_ref() == "length" => {
2304
+ Some(Ok(Value::Number(arr.borrow().len() as f64)))
2133
2305
  }
2134
- }
2306
+ _ => None,
2307
+ },
2135
2308
  _ => None,
2136
2309
  }
2137
2310
  }
@@ -2159,9 +2332,7 @@ impl Evaluator {
2159
2332
 
2160
2333
  fn call_func(&self, f: &Value, args: &[Value]) -> Result<Value, EvalError> {
2161
2334
  match f {
2162
- Value::Native(native_fn) => {
2163
- native_fn(args).map_err(EvalError::Error)
2164
- }
2335
+ Value::Native(native_fn) => native_fn(args).map_err(EvalError::Error),
2165
2336
  #[cfg(feature = "http")]
2166
2337
  Value::PromiseResolver(r) => {
2167
2338
  let value = args.first().cloned().unwrap_or(Value::Null);
@@ -2170,7 +2341,12 @@ impl Evaluator {
2170
2341
  .map_err(EvalError::Error)?;
2171
2342
  for reaction in reactions {
2172
2343
  match reaction {
2173
- crate::promise::Reaction::Then(on_fulfilled, on_rejected, ref resolve, ref reject) => {
2344
+ crate::promise::Reaction::Then(
2345
+ on_fulfilled,
2346
+ on_rejected,
2347
+ ref resolve,
2348
+ ref reject,
2349
+ ) => {
2174
2350
  let handler_result = if is_fulfilled {
2175
2351
  if let Some(ref h) = on_fulfilled {
2176
2352
  self.call_func(h, &[val.clone()])
@@ -2222,8 +2398,10 @@ impl Evaluator {
2222
2398
  #[cfg(feature = "http")]
2223
2399
  Value::Serve => self.run_http_server(args),
2224
2400
  Value::CoreFn(f) => {
2225
- let ca: Result<Vec<tishlang_core::Value>, String> =
2226
- args.iter().map(crate::value_convert::eval_to_core).collect();
2401
+ let ca: Result<Vec<tishlang_core::Value>, String> = args
2402
+ .iter()
2403
+ .map(crate::value_convert::eval_to_core)
2404
+ .collect();
2227
2405
  let ca = ca.map_err(EvalError::Error)?;
2228
2406
  Ok(crate::value_convert::core_to_eval(f(&ca)))
2229
2407
  }
@@ -2237,15 +2415,25 @@ impl Evaluator {
2237
2415
  Value::TimerBuiltin(name) => self.run_timer_builtin(name.as_ref(), args),
2238
2416
  Value::OpaqueMethod(opaque, method_name) => {
2239
2417
  let method = opaque.get_method(method_name.as_ref()).ok_or_else(|| {
2240
- EvalError::Error(format!("Method {} not found on {}", method_name, opaque.type_name()))
2418
+ EvalError::Error(format!(
2419
+ "Method {} not found on {}",
2420
+ method_name,
2421
+ opaque.type_name()
2422
+ ))
2241
2423
  })?;
2242
- let core_args: Result<Vec<tishlang_core::Value>, String> =
2243
- args.iter().map(crate::value_convert::eval_to_core).collect();
2424
+ let core_args: Result<Vec<tishlang_core::Value>, String> = args
2425
+ .iter()
2426
+ .map(crate::value_convert::eval_to_core)
2427
+ .collect();
2244
2428
  let core_args = core_args.map_err(EvalError::Error)?;
2245
2429
  let result = method(&core_args);
2246
2430
  Ok(crate::value_convert::core_to_eval(result))
2247
2431
  }
2248
- Value::Function { formals, rest_param, body } => {
2432
+ Value::Function {
2433
+ formals,
2434
+ rest_param,
2435
+ body,
2436
+ } => {
2249
2437
  let scope = Scope::child(Rc::clone(&self.scope));
2250
2438
  {
2251
2439
  let mut s = scope.borrow_mut();
@@ -2279,8 +2467,13 @@ impl Evaluator {
2279
2467
  }
2280
2468
  }
2281
2469
  if let Some(ref rest_name) = rest_param {
2282
- let rest_vals: Vec<Value> = args.iter().skip(formals.len()).cloned().collect();
2283
- s.set(Arc::clone(rest_name), Value::Array(Rc::new(RefCell::new(rest_vals))), true);
2470
+ let rest_vals: Vec<Value> =
2471
+ args.iter().skip(formals.len()).cloned().collect();
2472
+ s.set(
2473
+ Arc::clone(rest_name),
2474
+ Value::Array(Rc::new(RefCell::new(rest_vals))),
2475
+ true,
2476
+ );
2284
2477
  }
2285
2478
  }
2286
2479
  let mut eval = Evaluator {
@@ -2294,8 +2487,12 @@ impl Evaluator {
2294
2487
  Err(EvalError::Return(v)) => Ok(v),
2295
2488
  Err(EvalError::Throw(v)) => Err(EvalError::Throw(v)),
2296
2489
  Err(EvalError::Error(s)) => Err(EvalError::Error(s)),
2297
- Err(EvalError::Break) => Err(EvalError::Error("break outside loop".to_string())),
2298
- Err(EvalError::Continue) => Err(EvalError::Error("continue outside loop".to_string())),
2490
+ Err(EvalError::Break) => {
2491
+ Err(EvalError::Error("break outside loop".to_string()))
2492
+ }
2493
+ Err(EvalError::Continue) => {
2494
+ Err(EvalError::Error("continue outside loop".to_string()))
2495
+ }
2299
2496
  }
2300
2497
  }
2301
2498
  _ => Err(EvalError::Error("Not a function".to_string())),
@@ -2310,14 +2507,15 @@ impl Evaluator {
2310
2507
  args: &[Value],
2311
2508
  ) -> Result<Value, EvalError> {
2312
2509
  match method {
2313
- "then" => self.run_promise_then_core(
2314
- promise_ref,
2315
- args.first().cloned(),
2316
- args.get(1).cloned(),
2317
- ),
2510
+ "then" => {
2511
+ self.run_promise_then_core(promise_ref, args.first().cloned(), args.get(1).cloned())
2512
+ }
2318
2513
  "catch" => self.run_promise_then_core(promise_ref, None, args.first().cloned()),
2319
2514
  "finally" => self.run_promise_finally(promise_ref, args.first().cloned()),
2320
- _ => Err(EvalError::Error(format!("Unknown promise method: {}", method))),
2515
+ _ => Err(EvalError::Error(format!(
2516
+ "Unknown promise method: {}",
2517
+ method
2518
+ ))),
2321
2519
  }
2322
2520
  }
2323
2521
 
@@ -2418,7 +2616,12 @@ impl Evaluator {
2418
2616
  crate::promise::PromiseState::Pending { .. } => {
2419
2617
  crate::promise::add_reaction(
2420
2618
  state,
2421
- crate::promise::Reaction::Then(on_fulfilled, on_rejected, resolve.clone(), reject.clone()),
2619
+ crate::promise::Reaction::Then(
2620
+ on_fulfilled,
2621
+ on_rejected,
2622
+ resolve.clone(),
2623
+ reject.clone(),
2624
+ ),
2422
2625
  );
2423
2626
  }
2424
2627
  }
@@ -2527,8 +2730,11 @@ impl Evaluator {
2527
2730
  let port = port;
2528
2731
  std::thread::spawn(move || {
2529
2732
  std::thread::sleep(std::time::Duration::from_millis(50));
2530
- if let Ok(mut stream) = std::net::TcpStream::connect(format!("127.0.0.1:{}", port)) {
2531
- let _ = stream.write_all(b"GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n");
2733
+ if let Ok(mut stream) = std::net::TcpStream::connect(format!("127.0.0.1:{}", port))
2734
+ {
2735
+ let _ = stream.write_all(
2736
+ b"GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n",
2737
+ );
2532
2738
  let _ = stream.shutdown(std::net::Shutdown::Write);
2533
2739
  }
2534
2740
  });
@@ -2593,7 +2799,11 @@ impl Evaluator {
2593
2799
  tishlang_ast::DestructPattern::Array(elements) => {
2594
2800
  let arr = match value {
2595
2801
  Value::Array(a) => a.borrow().clone(),
2596
- _ => return Err(EvalError::Error("Cannot destructure non-array value".to_string())),
2802
+ _ => {
2803
+ return Err(EvalError::Error(
2804
+ "Cannot destructure non-array value".to_string(),
2805
+ ))
2806
+ }
2597
2807
  };
2598
2808
 
2599
2809
  for (i, elem) in elements.iter().enumerate() {
@@ -2623,7 +2833,11 @@ impl Evaluator {
2623
2833
  tishlang_ast::DestructPattern::Object(props) => {
2624
2834
  let obj = match value {
2625
2835
  Value::Object(o) => o.borrow().clone(),
2626
- _ => return Err(EvalError::Error("Cannot destructure non-object value".to_string())),
2836
+ _ => {
2837
+ return Err(EvalError::Error(
2838
+ "Cannot destructure non-object value".to_string(),
2839
+ ))
2840
+ }
2627
2841
  };
2628
2842
 
2629
2843
  for prop in props {
@@ -2647,7 +2861,12 @@ impl Evaluator {
2647
2861
  Ok(())
2648
2862
  }
2649
2863
 
2650
- fn bind_destruct_pattern(&mut self, pattern: &tishlang_ast::DestructPattern, value: &Value, mutable: bool) -> Result<(), EvalError> {
2864
+ fn bind_destruct_pattern(
2865
+ &mut self,
2866
+ pattern: &tishlang_ast::DestructPattern,
2867
+ value: &Value,
2868
+ mutable: bool,
2869
+ ) -> Result<(), EvalError> {
2651
2870
  Self::bind_destruct_pattern_scoped(&self.scope, pattern, value, mutable)
2652
2871
  }
2653
2872
 
@@ -2665,11 +2884,8 @@ impl Evaluator {
2665
2884
  Some(Value::Bool(b)) => tishlang_core::Value::Bool(*b),
2666
2885
  Some(_) => tishlang_core::Value::Number(0.0),
2667
2886
  };
2668
- let out = tishlang_builtins::string::last_index_of_str(
2669
- receiver.as_ref(),
2670
- search,
2671
- &position_core,
2672
- );
2887
+ let out =
2888
+ tishlang_builtins::string::last_index_of_str(receiver.as_ref(), search, &position_core);
2673
2889
  match out {
2674
2890
  tishlang_core::Value::Number(n) => Value::Number(n),
2675
2891
  _ => Value::Number(-1.0),
@@ -2953,7 +3169,9 @@ impl Evaluator {
2953
3169
  Ok((Value::Bool(false), rest))
2954
3170
  } else {
2955
3171
  let end = s
2956
- .find(|c: char| !c.is_ascii_digit() && c != '-' && c != '+' && c != '.' && c != 'e' && c != 'E')
3172
+ .find(|c: char| {
3173
+ !c.is_ascii_digit() && c != '-' && c != '+' && c != '.' && c != 'e' && c != 'E'
3174
+ })
2957
3175
  .unwrap_or(s.len());
2958
3176
  let num_str = &s[..end];
2959
3177
  let n: f64 = num_str.parse().map_err(|_| ())?;
@@ -2981,7 +3199,11 @@ impl Evaluator {
2981
3199
  .replace('\t', "\\t")
2982
3200
  ),
2983
3201
  Value::Array(arr) => {
2984
- let inner: Vec<String> = arr.borrow().iter().map(Self::json_stringify_value).collect();
3202
+ let inner: Vec<String> = arr
3203
+ .borrow()
3204
+ .iter()
3205
+ .map(Self::json_stringify_value)
3206
+ .collect();
2985
3207
  format!("[{}]", inner.join(","))
2986
3208
  }
2987
3209
  Value::Object(map) => {
@@ -3000,7 +3222,14 @@ impl Evaluator {
3000
3222
  })
3001
3223
  .collect();
3002
3224
  entries.sort_by(|a, b| a.0.cmp(&b.0));
3003
- format!("{{{}}}", entries.into_iter().map(|(_, s)| s).collect::<Vec<_>>().join(","))
3225
+ format!(
3226
+ "{{{}}}",
3227
+ entries
3228
+ .into_iter()
3229
+ .map(|(_, s)| s)
3230
+ .collect::<Vec<_>>()
3231
+ .join(",")
3232
+ )
3004
3233
  }
3005
3234
  Value::Function { .. } | Value::Native(_) => "null".to_string(),
3006
3235
  #[cfg(feature = "http")]
@@ -3011,7 +3240,8 @@ impl Evaluator {
3011
3240
  | Value::Promise(_)
3012
3241
  | Value::PromiseResolver(_)
3013
3242
  | Value::PromiseConstructor
3014
- | Value::BoundPromiseMethod(_, _) | Value::TimerBuiltin(_) => "null".to_string(),
3243
+ | Value::BoundPromiseMethod(_, _)
3244
+ | Value::TimerBuiltin(_) => "null".to_string(),
3015
3245
  #[cfg(feature = "regex")]
3016
3246
  Value::RegExp(_) => "null".to_string(),
3017
3247
  Value::Opaque(_) | Value::OpaqueMethod(_, _) => "null".to_string(),
@@ -3031,7 +3261,11 @@ impl Evaluator {
3031
3261
 
3032
3262
  fn object_keys(args: &[Value]) -> Result<Value, String> {
3033
3263
  if let Some(Value::Object(obj)) = args.first() {
3034
- let keys: Vec<Value> = obj.borrow().keys().map(|k| Value::String(Arc::clone(k))).collect();
3264
+ let keys: Vec<Value> = obj
3265
+ .borrow()
3266
+ .keys()
3267
+ .map(|k| Value::String(Arc::clone(k)))
3268
+ .collect();
3035
3269
  Ok(Value::Array(Rc::new(RefCell::new(keys))))
3036
3270
  } else {
3037
3271
  Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))))
@@ -3049,12 +3283,16 @@ impl Evaluator {
3049
3283
 
3050
3284
  fn object_entries(args: &[Value]) -> Result<Value, String> {
3051
3285
  if let Some(Value::Object(obj)) = args.first() {
3052
- let entries: Vec<Value> = obj.borrow().iter().map(|(k, v)| {
3053
- Value::Array(Rc::new(RefCell::new(vec![
3054
- Value::String(Arc::clone(k)),
3055
- v.clone(),
3056
- ])))
3057
- }).collect();
3286
+ let entries: Vec<Value> = obj
3287
+ .borrow()
3288
+ .iter()
3289
+ .map(|(k, v)| {
3290
+ Value::Array(Rc::new(RefCell::new(vec![
3291
+ Value::String(Arc::clone(k)),
3292
+ v.clone(),
3293
+ ])))
3294
+ })
3295
+ .collect();
3058
3296
  Ok(Value::Array(Rc::new(RefCell::new(entries))))
3059
3297
  } else {
3060
3298
  Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))))
@@ -3126,7 +3364,10 @@ impl Evaluator {
3126
3364
  .ok_or_else(|| "Promise.all requires an iterable".to_string())?;
3127
3365
  let values: Vec<Value> = match iterable {
3128
3366
  Value::Array(arr) => arr.borrow().clone(),
3129
- Value::String(s) => s.chars().map(|c| Value::String(c.to_string().into())).collect(),
3367
+ Value::String(s) => s
3368
+ .chars()
3369
+ .map(|c| Value::String(c.to_string().into()))
3370
+ .collect(),
3130
3371
  _ => return Err("Promise.all requires array or iterable".to_string()),
3131
3372
  };
3132
3373
  let mut results = Vec::with_capacity(values.len());
@@ -3136,7 +3377,8 @@ impl Evaluator {
3136
3377
  crate::promise::PromiseAwaitResult::Fulfilled(x) => results.push(x),
3137
3378
  crate::promise::PromiseAwaitResult::Rejected(x) => {
3138
3379
  let (promise, resolve_val, reject_val) = crate::promise::create_promise();
3139
- let (_, reject) = crate::promise::extract_resolvers(&resolve_val, &reject_val);
3380
+ let (_, reject) =
3381
+ crate::promise::extract_resolvers(&resolve_val, &reject_val);
3140
3382
  let _ = crate::promise::settle_promise(&reject, x, false);
3141
3383
  return Ok(promise);
3142
3384
  }
@@ -3147,7 +3389,8 @@ impl Evaluator {
3147
3389
  Ok(x) => results.push(crate::value_convert::core_to_eval(x)),
3148
3390
  Err(x) => {
3149
3391
  let (promise, resolve_val, reject_val) = crate::promise::create_promise();
3150
- let (_, reject) = crate::promise::extract_resolvers(&resolve_val, &reject_val);
3392
+ let (_, reject) =
3393
+ crate::promise::extract_resolvers(&resolve_val, &reject_val);
3151
3394
  let _ = crate::promise::settle_promise(
3152
3395
  &reject,
3153
3396
  crate::value_convert::core_to_eval(x),
@@ -3174,7 +3417,10 @@ impl Evaluator {
3174
3417
  .ok_or_else(|| "Promise.race requires an iterable".to_string())?;
3175
3418
  let values: Vec<Value> = match iterable {
3176
3419
  Value::Array(arr) => arr.borrow().clone(),
3177
- Value::String(s) => s.chars().map(|c| Value::String(c.to_string().into())).collect(),
3420
+ Value::String(s) => s
3421
+ .chars()
3422
+ .map(|c| Value::String(c.to_string().into()))
3423
+ .collect(),
3178
3424
  _ => return Err("Promise.race requires array or iterable".to_string()),
3179
3425
  };
3180
3426
  for v in values {
@@ -3182,7 +3428,8 @@ impl Evaluator {
3182
3428
  match p.block_until_settled() {
3183
3429
  Ok(x) => {
3184
3430
  let (promise, resolve_val, reject_val) = crate::promise::create_promise();
3185
- let (resolve, _) = crate::promise::extract_resolvers(&resolve_val, &reject_val);
3431
+ let (resolve, _) =
3432
+ crate::promise::extract_resolvers(&resolve_val, &reject_val);
3186
3433
  crate::promise::settle_promise(
3187
3434
  &resolve,
3188
3435
  crate::value_convert::core_to_eval(x),
@@ -3192,7 +3439,8 @@ impl Evaluator {
3192
3439
  }
3193
3440
  Err(x) => {
3194
3441
  let (promise, resolve_val, reject_val) = crate::promise::create_promise();
3195
- let (_, reject) = crate::promise::extract_resolvers(&resolve_val, &reject_val);
3442
+ let (_, reject) =
3443
+ crate::promise::extract_resolvers(&resolve_val, &reject_val);
3196
3444
  crate::promise::settle_promise(
3197
3445
  &reject,
3198
3446
  crate::value_convert::core_to_eval(x),
@@ -3206,13 +3454,15 @@ impl Evaluator {
3206
3454
  match crate::promise::block_until_settled(p) {
3207
3455
  crate::promise::PromiseAwaitResult::Fulfilled(x) => {
3208
3456
  let (promise, resolve_val, reject_val) = crate::promise::create_promise();
3209
- let (resolve, _) = crate::promise::extract_resolvers(&resolve_val, &reject_val);
3457
+ let (resolve, _) =
3458
+ crate::promise::extract_resolvers(&resolve_val, &reject_val);
3210
3459
  crate::promise::settle_promise(&resolve, x, true)?;
3211
3460
  return Ok(promise);
3212
3461
  }
3213
3462
  crate::promise::PromiseAwaitResult::Rejected(x) => {
3214
3463
  let (promise, resolve_val, reject_val) = crate::promise::create_promise();
3215
- let (_, reject) = crate::promise::extract_resolvers(&resolve_val, &reject_val);
3464
+ let (_, reject) =
3465
+ crate::promise::extract_resolvers(&resolve_val, &reject_val);
3216
3466
  crate::promise::settle_promise(&reject, x, false)?;
3217
3467
  return Ok(promise);
3218
3468
  }
@@ -3229,7 +3479,9 @@ impl Evaluator {
3229
3479
  for a in args {
3230
3480
  cv.push(crate::value_convert::eval_to_core(a)?);
3231
3481
  }
3232
- Ok(crate::value_convert::core_to_eval(tishlang_runtime::web_socket_client(&cv)))
3482
+ Ok(crate::value_convert::core_to_eval(
3483
+ tishlang_runtime::web_socket_client(&cv),
3484
+ ))
3233
3485
  }
3234
3486
 
3235
3487
  #[cfg(feature = "ws")]
@@ -3238,7 +3490,9 @@ impl Evaluator {
3238
3490
  for a in args {
3239
3491
  cv.push(crate::value_convert::eval_to_core(a)?);
3240
3492
  }
3241
- Ok(crate::value_convert::core_to_eval(tishlang_runtime::web_socket_server_construct(&cv)))
3493
+ Ok(crate::value_convert::core_to_eval(
3494
+ tishlang_runtime::web_socket_server_construct(&cv),
3495
+ ))
3242
3496
  }
3243
3497
 
3244
3498
  #[cfg(feature = "ws")]
@@ -3246,7 +3500,9 @@ impl Evaluator {
3246
3500
  let conn = args.first().ok_or("wsSend(conn, data) requires conn")?;
3247
3501
  let conn_core = crate::value_convert::eval_to_core(conn)?;
3248
3502
  let data = args.get(1).map(|v| v.to_string()).unwrap_or_default();
3249
- Ok(Value::Bool(tishlang_runtime::ws_send_native(&conn_core, &data)))
3503
+ Ok(Value::Bool(tishlang_runtime::ws_send_native(
3504
+ &conn_core, &data,
3505
+ )))
3250
3506
  }
3251
3507
 
3252
3508
  #[cfg(feature = "ws")]
@@ -3255,7 +3511,9 @@ impl Evaluator {
3255
3511
  for a in args {
3256
3512
  cv.push(crate::value_convert::eval_to_core(a)?);
3257
3513
  }
3258
- Ok(crate::value_convert::core_to_eval(tishlang_runtime::ws_broadcast_native(&cv)))
3514
+ Ok(crate::value_convert::core_to_eval(
3515
+ tishlang_runtime::ws_broadcast_native(&cv),
3516
+ ))
3259
3517
  }
3260
3518
 
3261
3519
  #[cfg(feature = "http")]
@@ -3309,7 +3567,6 @@ impl Evaluator {
3309
3567
  "await requires the http feature".to_string(),
3310
3568
  ))
3311
3569
  }
3312
-
3313
3570
  }
3314
3571
 
3315
3572
  #[derive(Debug)]