mustardscript 0.1.0 → 0.1.2

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 (96) hide show
  1. package/README.md +65 -22
  2. package/SECURITY.md +1 -1
  3. package/dist/index.js +2 -0
  4. package/dist/lib/executor.js +16 -1
  5. package/dist/lib/policy.js +301 -22
  6. package/dist/lib/progress.js +499 -113
  7. package/dist/lib/runtime.js +109 -40
  8. package/dist/lib/structured.js +327 -11
  9. package/dist/native-loader.js +11 -12
  10. package/index.d.ts +54 -6
  11. package/mustard.d.ts +23 -1
  12. package/package.json +34 -25
  13. package/Cargo.lock +0 -1579
  14. package/Cargo.toml +0 -40
  15. package/crates/mustard/Cargo.toml +0 -31
  16. package/crates/mustard/src/cancellation.rs +0 -28
  17. package/crates/mustard/src/diagnostic.rs +0 -145
  18. package/crates/mustard/src/ir.rs +0 -435
  19. package/crates/mustard/src/lib.rs +0 -21
  20. package/crates/mustard/src/limits.rs +0 -22
  21. package/crates/mustard/src/parser/expressions.rs +0 -723
  22. package/crates/mustard/src/parser/mod.rs +0 -115
  23. package/crates/mustard/src/parser/operators.rs +0 -105
  24. package/crates/mustard/src/parser/patterns.rs +0 -123
  25. package/crates/mustard/src/parser/scope.rs +0 -107
  26. package/crates/mustard/src/parser/statements.rs +0 -298
  27. package/crates/mustard/src/parser/tests/acceptance.rs +0 -339
  28. package/crates/mustard/src/parser/tests/mod.rs +0 -2
  29. package/crates/mustard/src/parser/tests/rejections.rs +0 -107
  30. package/crates/mustard/src/runtime/accounting.rs +0 -613
  31. package/crates/mustard/src/runtime/api.rs +0 -192
  32. package/crates/mustard/src/runtime/async_runtime/mod.rs +0 -5
  33. package/crates/mustard/src/runtime/async_runtime/promises.rs +0 -246
  34. package/crates/mustard/src/runtime/async_runtime/reactions.rs +0 -400
  35. package/crates/mustard/src/runtime/async_runtime/scheduler.rs +0 -224
  36. package/crates/mustard/src/runtime/builtins/arrays.rs +0 -1205
  37. package/crates/mustard/src/runtime/builtins/collections.rs +0 -573
  38. package/crates/mustard/src/runtime/builtins/install.rs +0 -501
  39. package/crates/mustard/src/runtime/builtins/intl.rs +0 -553
  40. package/crates/mustard/src/runtime/builtins/mod.rs +0 -25
  41. package/crates/mustard/src/runtime/builtins/objects.rs +0 -405
  42. package/crates/mustard/src/runtime/builtins/primitives.rs +0 -859
  43. package/crates/mustard/src/runtime/builtins/promises.rs +0 -335
  44. package/crates/mustard/src/runtime/builtins/regexp.rs +0 -356
  45. package/crates/mustard/src/runtime/builtins/strings.rs +0 -803
  46. package/crates/mustard/src/runtime/builtins/support.rs +0 -561
  47. package/crates/mustard/src/runtime/bytecode.rs +0 -123
  48. package/crates/mustard/src/runtime/compiler/assignments.rs +0 -690
  49. package/crates/mustard/src/runtime/compiler/bindings.rs +0 -92
  50. package/crates/mustard/src/runtime/compiler/context.rs +0 -46
  51. package/crates/mustard/src/runtime/compiler/control.rs +0 -342
  52. package/crates/mustard/src/runtime/compiler/expressions.rs +0 -372
  53. package/crates/mustard/src/runtime/compiler/mod.rs +0 -173
  54. package/crates/mustard/src/runtime/compiler/statements.rs +0 -459
  55. package/crates/mustard/src/runtime/conversions/boundary.rs +0 -293
  56. package/crates/mustard/src/runtime/conversions/coercions.rs +0 -217
  57. package/crates/mustard/src/runtime/conversions/errors.rs +0 -118
  58. package/crates/mustard/src/runtime/conversions/mod.rs +0 -14
  59. package/crates/mustard/src/runtime/conversions/operators.rs +0 -334
  60. package/crates/mustard/src/runtime/env.rs +0 -355
  61. package/crates/mustard/src/runtime/exceptions.rs +0 -377
  62. package/crates/mustard/src/runtime/gc.rs +0 -595
  63. package/crates/mustard/src/runtime/mod.rs +0 -318
  64. package/crates/mustard/src/runtime/properties.rs +0 -1762
  65. package/crates/mustard/src/runtime/serialization.rs +0 -127
  66. package/crates/mustard/src/runtime/shared.rs +0 -108
  67. package/crates/mustard/src/runtime/snapshot_validation_tests.rs +0 -93
  68. package/crates/mustard/src/runtime/state.rs +0 -652
  69. package/crates/mustard/src/runtime/tests/async_host.rs +0 -104
  70. package/crates/mustard/src/runtime/tests/collections.rs +0 -50
  71. package/crates/mustard/src/runtime/tests/diagnostics.rs +0 -36
  72. package/crates/mustard/src/runtime/tests/exceptions.rs +0 -122
  73. package/crates/mustard/src/runtime/tests/execution.rs +0 -553
  74. package/crates/mustard/src/runtime/tests/gc.rs +0 -533
  75. package/crates/mustard/src/runtime/tests/mod.rs +0 -56
  76. package/crates/mustard/src/runtime/tests/serialization.rs +0 -170
  77. package/crates/mustard/src/runtime/validation/bytecode.rs +0 -484
  78. package/crates/mustard/src/runtime/validation/mod.rs +0 -14
  79. package/crates/mustard/src/runtime/validation/policy.rs +0 -94
  80. package/crates/mustard/src/runtime/validation/snapshot.rs +0 -406
  81. package/crates/mustard/src/runtime/validation/walk.rs +0 -206
  82. package/crates/mustard/src/runtime/vm.rs +0 -1016
  83. package/crates/mustard/src/span.rs +0 -22
  84. package/crates/mustard/src/structured.rs +0 -107
  85. package/crates/mustard-bridge/Cargo.toml +0 -17
  86. package/crates/mustard-bridge/src/codec.rs +0 -46
  87. package/crates/mustard-bridge/src/dto.rs +0 -99
  88. package/crates/mustard-bridge/src/lib.rs +0 -12
  89. package/crates/mustard-bridge/src/operations.rs +0 -142
  90. package/crates/mustard-node/Cargo.toml +0 -24
  91. package/crates/mustard-node/build.rs +0 -3
  92. package/crates/mustard-node/src/lib.rs +0 -236
  93. package/crates/mustard-sidecar/Cargo.toml +0 -21
  94. package/crates/mustard-sidecar/src/lib.rs +0 -134
  95. package/crates/mustard-sidecar/src/main.rs +0 -36
  96. package/dist/install.js +0 -117
@@ -1,533 +0,0 @@
1
- use super::*;
2
-
3
- #[test]
4
- fn tracks_heap_growth_and_enforces_heap_limits() {
5
- let program = lower_to_bytecode(&compile("1;").expect("source should compile"))
6
- .expect("lowering should succeed");
7
- let mut runtime = Runtime::new(program.clone(), ExecutionOptions::default())
8
- .expect("runtime should initialize");
9
-
10
- let baseline_heap = runtime.heap_bytes_used;
11
- let array = runtime
12
- .insert_array(vec![Value::String("payload".to_string())], IndexMap::new())
13
- .expect("array allocation should succeed");
14
- assert!(runtime.heap_bytes_used > baseline_heap);
15
-
16
- let array_heap = runtime.heap_bytes_used;
17
- runtime
18
- .set_property(
19
- Value::Array(array),
20
- Value::String("extra".to_string()),
21
- Value::String("more payload".to_string()),
22
- )
23
- .expect("array growth should succeed");
24
- assert!(runtime.heap_bytes_used > array_heap);
25
-
26
- let mut heap_limited = Runtime::new(program.clone(), ExecutionOptions::default())
27
- .expect("runtime should initialize");
28
- heap_limited.limits.heap_limit_bytes = heap_limited.heap_bytes_used;
29
- let error = heap_limited
30
- .insert_array(vec![Value::String("payload".to_string())], IndexMap::new())
31
- .expect_err("next allocation should exceed the heap limit");
32
- assert!(error.to_string().contains("heap limit exceeded"));
33
-
34
- let mut allocation_limited =
35
- Runtime::new(program, ExecutionOptions::default()).expect("runtime should initialize");
36
- allocation_limited.limits.allocation_budget = allocation_limited.allocation_count;
37
- let error = allocation_limited
38
- .insert_object(IndexMap::new(), ObjectKind::Plain)
39
- .expect_err("next allocation should exhaust the allocation budget");
40
- assert!(error.to_string().contains("allocation budget exhausted"));
41
- }
42
-
43
- #[test]
44
- fn iterators_participate_in_heap_accounting_and_gc() {
45
- let program = lower_to_bytecode(&compile("0;").expect("source should compile"))
46
- .expect("lowering should succeed");
47
- let mut runtime = Runtime::new(program, ExecutionOptions::default()).expect("runtime init");
48
-
49
- let baseline_heap = runtime.heap_bytes_used;
50
- let kept_array = runtime
51
- .insert_array(
52
- vec![Value::Number(1.0), Value::Number(2.0)],
53
- IndexMap::new(),
54
- )
55
- .expect("kept array should allocate");
56
- let kept_iterator = runtime
57
- .insert_iterator(IteratorState::Array(ArrayIteratorState {
58
- array: kept_array,
59
- next_index: 1,
60
- }))
61
- .expect("kept iterator should allocate");
62
- assert!(runtime.heap_bytes_used > baseline_heap);
63
-
64
- let frame_env = runtime
65
- .new_env(Some(runtime.globals))
66
- .expect("frame env should allocate");
67
- let iterator_cell = runtime
68
- .insert_cell(Value::Iterator(kept_iterator), true, true)
69
- .expect("iterator cell should allocate");
70
- runtime
71
- .envs
72
- .get_mut(frame_env)
73
- .expect("frame env should exist")
74
- .bindings
75
- .insert("\0kept_iter".to_string(), iterator_cell);
76
- runtime
77
- .refresh_env_accounting(frame_env)
78
- .expect("frame env accounting should refresh");
79
- runtime.frames.push(Frame {
80
- function_id: 0,
81
- ip: 0,
82
- env: frame_env,
83
- scope_stack: Vec::new(),
84
- stack: Vec::new(),
85
- handlers: Vec::new(),
86
- pending_exception: None,
87
- pending_completions: Vec::new(),
88
- active_finally: Vec::new(),
89
- async_promise: None,
90
- });
91
-
92
- let garbage_array = runtime
93
- .insert_array(vec![Value::Number(9.0)], IndexMap::new())
94
- .expect("garbage array should allocate");
95
- let garbage_iterator = runtime
96
- .insert_iterator(IteratorState::Array(ArrayIteratorState {
97
- array: garbage_array,
98
- next_index: 0,
99
- }))
100
- .expect("garbage iterator should allocate");
101
-
102
- runtime.collect_garbage().expect("gc should succeed");
103
- assert!(runtime.arrays.contains_key(kept_array));
104
- assert!(runtime.iterators.contains_key(kept_iterator));
105
- assert!(!runtime.arrays.contains_key(garbage_array));
106
- assert!(!runtime.iterators.contains_key(garbage_iterator));
107
-
108
- runtime.frames.clear();
109
- runtime.collect_garbage().expect("gc should succeed");
110
- assert!(!runtime.arrays.contains_key(kept_array));
111
- assert!(!runtime.iterators.contains_key(kept_iterator));
112
- }
113
-
114
- #[test]
115
- fn map_and_set_iterators_keep_keyed_collections_alive_for_gc() {
116
- let program = lower_to_bytecode(&compile("0;").expect("source should compile"))
117
- .expect("lowering should succeed");
118
- let mut runtime = Runtime::new(program, ExecutionOptions::default()).expect("runtime init");
119
-
120
- let kept_map = runtime.insert_map(Vec::new()).expect("map should allocate");
121
- runtime
122
- .map_set(
123
- kept_map,
124
- Value::String("alpha".to_string()),
125
- Value::Number(1.0),
126
- )
127
- .expect("map entry should insert");
128
- let kept_set = runtime.insert_set(Vec::new()).expect("set should allocate");
129
- runtime
130
- .set_add(kept_set, Value::String("beta".to_string()))
131
- .expect("set entry should insert");
132
- let kept_map_iterator = runtime
133
- .insert_iterator(IteratorState::MapEntries(MapIteratorState {
134
- map: kept_map,
135
- next_index: 0,
136
- }))
137
- .expect("map iterator should allocate");
138
- let kept_set_iterator = runtime
139
- .insert_iterator(IteratorState::SetValues(SetIteratorState {
140
- set: kept_set,
141
- next_index: 0,
142
- }))
143
- .expect("set iterator should allocate");
144
-
145
- let frame_env = runtime
146
- .new_env(Some(runtime.globals))
147
- .expect("frame env should allocate");
148
- let map_iterator_cell = runtime
149
- .insert_cell(Value::Iterator(kept_map_iterator), true, true)
150
- .expect("map iterator cell should allocate");
151
- let set_iterator_cell = runtime
152
- .insert_cell(Value::Iterator(kept_set_iterator), true, true)
153
- .expect("set iterator cell should allocate");
154
- let env = runtime
155
- .envs
156
- .get_mut(frame_env)
157
- .expect("frame env should exist");
158
- env.bindings
159
- .insert("\0kept_map_iter".to_string(), map_iterator_cell);
160
- env.bindings
161
- .insert("\0kept_set_iter".to_string(), set_iterator_cell);
162
- runtime
163
- .refresh_env_accounting(frame_env)
164
- .expect("frame env accounting should refresh");
165
- runtime.frames.push(Frame {
166
- function_id: 0,
167
- ip: 0,
168
- env: frame_env,
169
- scope_stack: Vec::new(),
170
- stack: Vec::new(),
171
- handlers: Vec::new(),
172
- pending_exception: None,
173
- pending_completions: Vec::new(),
174
- active_finally: Vec::new(),
175
- async_promise: None,
176
- });
177
-
178
- let garbage_map = runtime.insert_map(Vec::new()).expect("map should allocate");
179
- runtime
180
- .map_set(
181
- garbage_map,
182
- Value::String("gamma".to_string()),
183
- Value::Number(2.0),
184
- )
185
- .expect("garbage map entry should insert");
186
- let garbage_set = runtime.insert_set(Vec::new()).expect("set should allocate");
187
- runtime
188
- .set_add(garbage_set, Value::String("delta".to_string()))
189
- .expect("garbage set entry should insert");
190
- let garbage_map_iterator = runtime
191
- .insert_iterator(IteratorState::MapEntries(MapIteratorState {
192
- map: garbage_map,
193
- next_index: 0,
194
- }))
195
- .expect("garbage map iterator should allocate");
196
- let garbage_set_iterator = runtime
197
- .insert_iterator(IteratorState::SetValues(SetIteratorState {
198
- set: garbage_set,
199
- next_index: 0,
200
- }))
201
- .expect("garbage set iterator should allocate");
202
-
203
- runtime.collect_garbage().expect("gc should succeed");
204
- assert!(runtime.maps.contains_key(kept_map));
205
- assert!(runtime.sets.contains_key(kept_set));
206
- assert!(runtime.iterators.contains_key(kept_map_iterator));
207
- assert!(runtime.iterators.contains_key(kept_set_iterator));
208
- assert!(!runtime.maps.contains_key(garbage_map));
209
- assert!(!runtime.sets.contains_key(garbage_set));
210
- assert!(!runtime.iterators.contains_key(garbage_map_iterator));
211
- assert!(!runtime.iterators.contains_key(garbage_set_iterator));
212
- }
213
-
214
- #[test]
215
- fn promise_reactions_keep_target_promises_alive_for_gc() {
216
- let program = lower_to_bytecode(&compile("0;").expect("source should compile"))
217
- .expect("lowering should succeed");
218
- let mut runtime = Runtime::new(program, ExecutionOptions::default()).expect("runtime init");
219
-
220
- let kept_source = runtime
221
- .insert_promise(PromiseState::Pending)
222
- .expect("source promise should allocate");
223
- let kept_target = runtime
224
- .insert_promise(PromiseState::Pending)
225
- .expect("target promise should allocate");
226
- runtime
227
- .attach_promise_reaction(
228
- kept_source,
229
- PromiseReaction::Then {
230
- target: kept_target,
231
- on_fulfilled: None,
232
- on_rejected: None,
233
- },
234
- )
235
- .expect("reaction should attach");
236
-
237
- let frame_env = runtime
238
- .new_env(Some(runtime.globals))
239
- .expect("frame env should allocate");
240
- let source_cell = runtime
241
- .insert_cell(Value::Promise(kept_source), true, true)
242
- .expect("promise cell should allocate");
243
- runtime
244
- .envs
245
- .get_mut(frame_env)
246
- .expect("frame env should exist")
247
- .bindings
248
- .insert("\0kept_promise".to_string(), source_cell);
249
- runtime
250
- .refresh_env_accounting(frame_env)
251
- .expect("frame env accounting should refresh");
252
- runtime.frames.push(Frame {
253
- function_id: 0,
254
- ip: 0,
255
- env: frame_env,
256
- scope_stack: Vec::new(),
257
- stack: Vec::new(),
258
- handlers: Vec::new(),
259
- pending_exception: None,
260
- pending_completions: Vec::new(),
261
- active_finally: Vec::new(),
262
- async_promise: None,
263
- });
264
-
265
- let garbage_source = runtime
266
- .insert_promise(PromiseState::Pending)
267
- .expect("garbage promise should allocate");
268
- let garbage_target = runtime
269
- .insert_promise(PromiseState::Pending)
270
- .expect("garbage target should allocate");
271
- runtime
272
- .attach_promise_reaction(
273
- garbage_source,
274
- PromiseReaction::Then {
275
- target: garbage_target,
276
- on_fulfilled: None,
277
- on_rejected: None,
278
- },
279
- )
280
- .expect("garbage reaction should attach");
281
-
282
- runtime.collect_garbage().expect("gc should succeed");
283
- assert!(runtime.promises.contains_key(kept_source));
284
- assert!(runtime.promises.contains_key(kept_target));
285
- assert!(!runtime.promises.contains_key(garbage_source));
286
- assert!(!runtime.promises.contains_key(garbage_target));
287
- }
288
-
289
- #[test]
290
- fn keyed_collections_participate_in_heap_accounting_and_gc() {
291
- let program = lower_to_bytecode(&compile("0;").expect("source should compile"))
292
- .expect("lowering should succeed");
293
- let mut runtime = Runtime::new(program, ExecutionOptions::default()).expect("runtime init");
294
-
295
- let baseline_heap = runtime.heap_bytes_used;
296
- let kept_map = runtime.insert_map(Vec::new()).expect("map should allocate");
297
- let kept_set = runtime.insert_set(Vec::new()).expect("set should allocate");
298
- runtime
299
- .map_set(
300
- kept_map,
301
- Value::String("set".to_string()),
302
- Value::Set(kept_set),
303
- )
304
- .expect("map should store the set");
305
- runtime
306
- .set_add(kept_set, Value::Map(kept_map))
307
- .expect("set should store the map");
308
- assert!(runtime.heap_bytes_used > baseline_heap);
309
-
310
- let frame_env = runtime
311
- .new_env(Some(runtime.globals))
312
- .expect("frame env should allocate");
313
- let map_cell = runtime
314
- .insert_cell(Value::Map(kept_map), true, true)
315
- .expect("map cell should allocate");
316
- runtime
317
- .envs
318
- .get_mut(frame_env)
319
- .expect("frame env should exist")
320
- .bindings
321
- .insert("\0kept_map".to_string(), map_cell);
322
- runtime
323
- .refresh_env_accounting(frame_env)
324
- .expect("frame env accounting should refresh");
325
- runtime.frames.push(Frame {
326
- function_id: 0,
327
- ip: 0,
328
- env: frame_env,
329
- scope_stack: Vec::new(),
330
- stack: Vec::new(),
331
- handlers: Vec::new(),
332
- pending_exception: None,
333
- pending_completions: Vec::new(),
334
- active_finally: Vec::new(),
335
- async_promise: None,
336
- });
337
-
338
- let garbage_map = runtime
339
- .insert_map(Vec::new())
340
- .expect("garbage map should allocate");
341
- let garbage_set = runtime
342
- .insert_set(Vec::new())
343
- .expect("garbage set should allocate");
344
- runtime
345
- .map_set(
346
- garbage_map,
347
- Value::String("set".to_string()),
348
- Value::Set(garbage_set),
349
- )
350
- .expect("garbage map should store the set");
351
- runtime
352
- .set_add(garbage_set, Value::Map(garbage_map))
353
- .expect("garbage set should store the map");
354
-
355
- runtime.collect_garbage().expect("gc should succeed");
356
- assert!(runtime.maps.contains_key(kept_map));
357
- assert!(runtime.sets.contains_key(kept_set));
358
- assert!(!runtime.maps.contains_key(garbage_map));
359
- assert!(!runtime.sets.contains_key(garbage_set));
360
-
361
- runtime.frames.clear();
362
- runtime.collect_garbage().expect("gc should succeed");
363
- assert!(!runtime.maps.contains_key(kept_map));
364
- assert!(!runtime.sets.contains_key(kept_set));
365
- }
366
-
367
- #[test]
368
- fn garbage_collection_marks_runtime_roots_and_collects_cycles() {
369
- let program = lower_to_bytecode(&compile("0;").expect("source should compile"))
370
- .expect("lowering should succeed");
371
- let mut runtime =
372
- Runtime::new(program.clone(), ExecutionOptions::default()).expect("runtime init");
373
-
374
- let closure_env = runtime
375
- .new_env(Some(runtime.globals))
376
- .expect("closure env should allocate");
377
- let rooted_closure = runtime
378
- .insert_closure(program.root, closure_env)
379
- .expect("closure should allocate");
380
- let rooted_object = runtime
381
- .insert_object(
382
- IndexMap::from([("closure".to_string(), Value::Closure(rooted_closure))]),
383
- ObjectKind::Plain,
384
- )
385
- .expect("object should allocate");
386
- let rooted_array = runtime
387
- .insert_array(vec![Value::Object(rooted_object)], IndexMap::new())
388
- .expect("array should allocate");
389
-
390
- let frame_env = runtime
391
- .new_env(Some(runtime.globals))
392
- .expect("frame env should allocate");
393
- let rooted_cell = runtime
394
- .insert_cell(Value::Array(rooted_array), true, true)
395
- .expect("cell should allocate");
396
- runtime
397
- .envs
398
- .get_mut(frame_env)
399
- .expect("frame env should exist")
400
- .bindings
401
- .insert("kept".to_string(), rooted_cell);
402
- runtime
403
- .refresh_env_accounting(frame_env)
404
- .expect("frame env accounting should refresh");
405
- runtime.frames.push(Frame {
406
- function_id: program.root,
407
- ip: 0,
408
- env: frame_env,
409
- scope_stack: vec![closure_env],
410
- stack: vec![Value::Closure(rooted_closure)],
411
- handlers: vec![ExceptionHandler {
412
- catch: None,
413
- finally: None,
414
- env: closure_env,
415
- scope_stack_len: 0,
416
- stack_len: 0,
417
- }],
418
- pending_exception: Some(Value::Object(rooted_object)),
419
- pending_completions: vec![
420
- CompletionRecord::Return(Value::Array(rooted_array)),
421
- CompletionRecord::Throw(Value::Closure(rooted_closure)),
422
- ],
423
- active_finally: Vec::new(),
424
- async_promise: None,
425
- });
426
-
427
- let garbage_env = runtime.new_env(None).expect("garbage env should allocate");
428
- let garbage_left = runtime
429
- .insert_object(IndexMap::new(), ObjectKind::Plain)
430
- .expect("garbage object should allocate");
431
- let garbage_right = runtime
432
- .insert_object(IndexMap::new(), ObjectKind::Plain)
433
- .expect("garbage object should allocate");
434
- let garbage_array = runtime
435
- .insert_array(vec![Value::Object(garbage_left)], IndexMap::new())
436
- .expect("garbage array should allocate");
437
- let garbage_closure = runtime
438
- .insert_closure(program.root, garbage_env)
439
- .expect("garbage closure should allocate");
440
- runtime
441
- .set_property(
442
- Value::Object(garbage_left),
443
- Value::String("peer".to_string()),
444
- Value::Object(garbage_right),
445
- )
446
- .expect("left cycle should update");
447
- runtime
448
- .set_property(
449
- Value::Object(garbage_right),
450
- Value::String("peer".to_string()),
451
- Value::Object(garbage_left),
452
- )
453
- .expect("right cycle should update");
454
- runtime
455
- .set_property(
456
- Value::Object(garbage_right),
457
- Value::String("items".to_string()),
458
- Value::Array(garbage_array),
459
- )
460
- .expect("array cycle should update");
461
- runtime
462
- .set_property(
463
- Value::Object(garbage_left),
464
- Value::String("closure".to_string()),
465
- Value::Closure(garbage_closure),
466
- )
467
- .expect("closure cycle should update");
468
- let garbage_cell = runtime
469
- .insert_cell(Value::Object(garbage_left), true, true)
470
- .expect("garbage cell should allocate");
471
- runtime
472
- .envs
473
- .get_mut(garbage_env)
474
- .expect("garbage env should exist")
475
- .bindings
476
- .insert("garbage".to_string(), garbage_cell);
477
- runtime
478
- .refresh_env_accounting(garbage_env)
479
- .expect("garbage env accounting should refresh");
480
-
481
- let stats = runtime.collect_garbage().expect("gc should succeed");
482
-
483
- assert!(stats.reclaimed_allocations >= 5);
484
- assert!(stats.reclaimed_bytes > 0);
485
- assert!(runtime.envs.contains_key(frame_env));
486
- assert!(runtime.envs.contains_key(closure_env));
487
- assert!(runtime.cells.contains_key(rooted_cell));
488
- assert!(runtime.objects.contains_key(rooted_object));
489
- assert!(runtime.arrays.contains_key(rooted_array));
490
- assert!(runtime.closures.contains_key(rooted_closure));
491
-
492
- assert!(!runtime.envs.contains_key(garbage_env));
493
- assert!(!runtime.cells.contains_key(garbage_cell));
494
- assert!(!runtime.objects.contains_key(garbage_left));
495
- assert!(!runtime.objects.contains_key(garbage_right));
496
- assert!(!runtime.arrays.contains_key(garbage_array));
497
- assert!(!runtime.closures.contains_key(garbage_closure));
498
- }
499
-
500
- #[test]
501
- fn garbage_collection_reclaims_cyclic_garbage_under_execution_pressure() {
502
- let program = compile(
503
- r#"
504
- let total = 0;
505
- for (let i = 0; i < 120; i += 1) {
506
- let left = {};
507
- let right = {};
508
- left.peer = right;
509
- right.peer = left;
510
- total += i;
511
- }
512
- total;
513
- "#,
514
- )
515
- .expect("source should compile");
516
- let value = execute(
517
- &program,
518
- ExecutionOptions {
519
- limits: RuntimeLimits {
520
- heap_limit_bytes: 24 * 1024,
521
- allocation_budget: 256,
522
- ..RuntimeLimits::default()
523
- },
524
- cancellation_token: None,
525
- ..ExecutionOptions::default()
526
- },
527
- )
528
- .expect("cyclic garbage should be reclaimed");
529
- assert_eq!(
530
- value,
531
- StructuredValue::Number(StructuredNumber::Finite(7140.0))
532
- );
533
- }
@@ -1,56 +0,0 @@
1
- use super::*;
2
- use crate::{compile, limits::RuntimeLimits};
3
-
4
- mod async_host;
5
- mod collections;
6
- mod diagnostics;
7
- mod exceptions;
8
- mod execution;
9
- mod gc;
10
- mod serialization;
11
-
12
- fn test_function(code: Vec<Instruction>) -> FunctionPrototype {
13
- FunctionPrototype {
14
- name: None,
15
- length: 0,
16
- display_source: String::new(),
17
- params: Vec::new(),
18
- rest: None,
19
- code,
20
- is_async: false,
21
- is_arrow: false,
22
- span: SourceSpan::new(0, 0),
23
- }
24
- }
25
-
26
- fn invalid_program(code: Vec<Instruction>) -> BytecodeProgram {
27
- BytecodeProgram {
28
- functions: vec![test_function(code)],
29
- root: 0,
30
- }
31
- }
32
-
33
- fn number(value: f64) -> StructuredValue {
34
- StructuredValue::Number(StructuredNumber::Finite(value))
35
- }
36
-
37
- fn options_with_capabilities(capabilities: &[&str]) -> ExecutionOptions {
38
- ExecutionOptions {
39
- capabilities: capabilities.iter().map(|value| (*value).to_string()).collect(),
40
- ..ExecutionOptions::default()
41
- }
42
- }
43
-
44
- fn suspend(source: &str, capabilities: &[&str]) -> Suspension {
45
- let program = compile(source).expect("source should compile");
46
- match start(&program, options_with_capabilities(capabilities)).expect("execution should suspend")
47
- {
48
- ExecutionStep::Suspended(suspension) => *suspension,
49
- other => panic!("expected suspension, got {other:?}"),
50
- }
51
- }
52
-
53
- fn run(source: &str) -> StructuredValue {
54
- let program = compile(source).expect("source should compile");
55
- execute(&program, ExecutionOptions::default()).expect("program should run")
56
- }