mustardscript 0.1.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 (99) hide show
  1. package/Cargo.lock +1579 -0
  2. package/Cargo.toml +40 -0
  3. package/LICENSE +201 -0
  4. package/README.md +828 -0
  5. package/SECURITY.md +34 -0
  6. package/crates/mustard/Cargo.toml +31 -0
  7. package/crates/mustard/src/cancellation.rs +28 -0
  8. package/crates/mustard/src/diagnostic.rs +145 -0
  9. package/crates/mustard/src/ir.rs +435 -0
  10. package/crates/mustard/src/lib.rs +21 -0
  11. package/crates/mustard/src/limits.rs +22 -0
  12. package/crates/mustard/src/parser/expressions.rs +723 -0
  13. package/crates/mustard/src/parser/mod.rs +115 -0
  14. package/crates/mustard/src/parser/operators.rs +105 -0
  15. package/crates/mustard/src/parser/patterns.rs +123 -0
  16. package/crates/mustard/src/parser/scope.rs +107 -0
  17. package/crates/mustard/src/parser/statements.rs +298 -0
  18. package/crates/mustard/src/parser/tests/acceptance.rs +339 -0
  19. package/crates/mustard/src/parser/tests/mod.rs +2 -0
  20. package/crates/mustard/src/parser/tests/rejections.rs +107 -0
  21. package/crates/mustard/src/runtime/accounting.rs +613 -0
  22. package/crates/mustard/src/runtime/api.rs +192 -0
  23. package/crates/mustard/src/runtime/async_runtime/mod.rs +5 -0
  24. package/crates/mustard/src/runtime/async_runtime/promises.rs +246 -0
  25. package/crates/mustard/src/runtime/async_runtime/reactions.rs +400 -0
  26. package/crates/mustard/src/runtime/async_runtime/scheduler.rs +224 -0
  27. package/crates/mustard/src/runtime/builtins/arrays.rs +1205 -0
  28. package/crates/mustard/src/runtime/builtins/collections.rs +573 -0
  29. package/crates/mustard/src/runtime/builtins/install.rs +501 -0
  30. package/crates/mustard/src/runtime/builtins/intl.rs +553 -0
  31. package/crates/mustard/src/runtime/builtins/mod.rs +25 -0
  32. package/crates/mustard/src/runtime/builtins/objects.rs +405 -0
  33. package/crates/mustard/src/runtime/builtins/primitives.rs +859 -0
  34. package/crates/mustard/src/runtime/builtins/promises.rs +335 -0
  35. package/crates/mustard/src/runtime/builtins/regexp.rs +356 -0
  36. package/crates/mustard/src/runtime/builtins/strings.rs +803 -0
  37. package/crates/mustard/src/runtime/builtins/support.rs +561 -0
  38. package/crates/mustard/src/runtime/bytecode.rs +123 -0
  39. package/crates/mustard/src/runtime/compiler/assignments.rs +690 -0
  40. package/crates/mustard/src/runtime/compiler/bindings.rs +92 -0
  41. package/crates/mustard/src/runtime/compiler/context.rs +46 -0
  42. package/crates/mustard/src/runtime/compiler/control.rs +342 -0
  43. package/crates/mustard/src/runtime/compiler/expressions.rs +372 -0
  44. package/crates/mustard/src/runtime/compiler/mod.rs +173 -0
  45. package/crates/mustard/src/runtime/compiler/statements.rs +459 -0
  46. package/crates/mustard/src/runtime/conversions/boundary.rs +293 -0
  47. package/crates/mustard/src/runtime/conversions/coercions.rs +217 -0
  48. package/crates/mustard/src/runtime/conversions/errors.rs +118 -0
  49. package/crates/mustard/src/runtime/conversions/mod.rs +14 -0
  50. package/crates/mustard/src/runtime/conversions/operators.rs +334 -0
  51. package/crates/mustard/src/runtime/env.rs +355 -0
  52. package/crates/mustard/src/runtime/exceptions.rs +377 -0
  53. package/crates/mustard/src/runtime/gc.rs +595 -0
  54. package/crates/mustard/src/runtime/mod.rs +318 -0
  55. package/crates/mustard/src/runtime/properties.rs +1762 -0
  56. package/crates/mustard/src/runtime/serialization.rs +127 -0
  57. package/crates/mustard/src/runtime/shared.rs +108 -0
  58. package/crates/mustard/src/runtime/snapshot_validation_tests.rs +93 -0
  59. package/crates/mustard/src/runtime/state.rs +652 -0
  60. package/crates/mustard/src/runtime/tests/async_host.rs +104 -0
  61. package/crates/mustard/src/runtime/tests/collections.rs +50 -0
  62. package/crates/mustard/src/runtime/tests/diagnostics.rs +36 -0
  63. package/crates/mustard/src/runtime/tests/exceptions.rs +122 -0
  64. package/crates/mustard/src/runtime/tests/execution.rs +553 -0
  65. package/crates/mustard/src/runtime/tests/gc.rs +533 -0
  66. package/crates/mustard/src/runtime/tests/mod.rs +56 -0
  67. package/crates/mustard/src/runtime/tests/serialization.rs +170 -0
  68. package/crates/mustard/src/runtime/validation/bytecode.rs +484 -0
  69. package/crates/mustard/src/runtime/validation/mod.rs +14 -0
  70. package/crates/mustard/src/runtime/validation/policy.rs +94 -0
  71. package/crates/mustard/src/runtime/validation/snapshot.rs +406 -0
  72. package/crates/mustard/src/runtime/validation/walk.rs +206 -0
  73. package/crates/mustard/src/runtime/vm.rs +1016 -0
  74. package/crates/mustard/src/span.rs +22 -0
  75. package/crates/mustard/src/structured.rs +107 -0
  76. package/crates/mustard-bridge/Cargo.toml +17 -0
  77. package/crates/mustard-bridge/src/codec.rs +46 -0
  78. package/crates/mustard-bridge/src/dto.rs +99 -0
  79. package/crates/mustard-bridge/src/lib.rs +12 -0
  80. package/crates/mustard-bridge/src/operations.rs +142 -0
  81. package/crates/mustard-node/Cargo.toml +24 -0
  82. package/crates/mustard-node/build.rs +3 -0
  83. package/crates/mustard-node/src/lib.rs +236 -0
  84. package/crates/mustard-sidecar/Cargo.toml +21 -0
  85. package/crates/mustard-sidecar/src/lib.rs +134 -0
  86. package/crates/mustard-sidecar/src/main.rs +36 -0
  87. package/dist/index.js +20 -0
  88. package/dist/install.js +117 -0
  89. package/dist/lib/cancellation.js +124 -0
  90. package/dist/lib/errors.js +46 -0
  91. package/dist/lib/executor.js +555 -0
  92. package/dist/lib/policy.js +292 -0
  93. package/dist/lib/progress.js +356 -0
  94. package/dist/lib/runtime.js +109 -0
  95. package/dist/lib/structured.js +286 -0
  96. package/dist/native-loader.js +227 -0
  97. package/index.d.ts +23 -0
  98. package/mustard.d.ts +220 -0
  99. package/package.json +97 -0
@@ -0,0 +1,573 @@
1
+ use crate::runtime::properties::canonicalize_collection_key;
2
+
3
+ use super::*;
4
+
5
+ impl Runtime {
6
+ pub(crate) fn construct_map(&mut self, args: &[Value]) -> MustardResult<Value> {
7
+ let map = self.insert_map(Vec::new())?;
8
+ let iterable = args.first().cloned().unwrap_or(Value::Undefined);
9
+ if matches!(iterable, Value::Null | Value::Undefined) {
10
+ return Ok(Value::Map(map));
11
+ }
12
+
13
+ let iterator = self.create_iterator(iterable)?;
14
+ loop {
15
+ let (entry, done) = self.iterator_next(iterator.clone())?;
16
+ if done {
17
+ break;
18
+ }
19
+ let items: Vec<Value> = match entry {
20
+ Value::Array(array) => self
21
+ .arrays
22
+ .get(array)
23
+ .ok_or_else(|| MustardError::runtime("array missing"))?
24
+ .elements
25
+ .iter()
26
+ .map(|value| value.clone().unwrap_or(Value::Undefined))
27
+ .collect(),
28
+ _ => {
29
+ return Err(MustardError::runtime(
30
+ "TypeError: Map constructor expects an iterable of [key, value] pairs",
31
+ ));
32
+ }
33
+ };
34
+ let key = items.first().cloned().unwrap_or(Value::Undefined);
35
+ let value = items.get(1).cloned().unwrap_or(Value::Undefined);
36
+ self.map_set(map, key, value)?;
37
+ }
38
+
39
+ Ok(Value::Map(map))
40
+ }
41
+
42
+ pub(crate) fn construct_set(&mut self, args: &[Value]) -> MustardResult<Value> {
43
+ let set = self.insert_set(Vec::new())?;
44
+ let iterable = args.first().cloned().unwrap_or(Value::Undefined);
45
+ if matches!(iterable, Value::Null | Value::Undefined) {
46
+ return Ok(Value::Set(set));
47
+ }
48
+
49
+ let iterator = self.create_iterator(iterable)?;
50
+ loop {
51
+ let (value, done) = self.iterator_next(iterator.clone())?;
52
+ if done {
53
+ break;
54
+ }
55
+ self.set_add(set, value)?;
56
+ }
57
+
58
+ Ok(Value::Set(set))
59
+ }
60
+
61
+ fn map_receiver(&self, value: Value, method: &str) -> MustardResult<MapKey> {
62
+ match value {
63
+ Value::Map(key) => Ok(key),
64
+ _ => Err(MustardError::runtime(format!(
65
+ "TypeError: Map.prototype.{method} called on incompatible receiver",
66
+ ))),
67
+ }
68
+ }
69
+
70
+ fn set_receiver(&self, value: Value, method: &str) -> MustardResult<SetKey> {
71
+ match value {
72
+ Value::Set(key) => Ok(key),
73
+ _ => Err(MustardError::runtime(format!(
74
+ "TypeError: Set.prototype.{method} called on incompatible receiver",
75
+ ))),
76
+ }
77
+ }
78
+
79
+ fn iterator_receiver(&self, value: Value, method: &str) -> MustardResult<IteratorKey> {
80
+ match value {
81
+ Value::Iterator(key) => Ok(key),
82
+ _ => Err(MustardError::runtime(format!(
83
+ "TypeError: iterator.{method} called on incompatible receiver",
84
+ ))),
85
+ }
86
+ }
87
+
88
+ fn collection_callback(&self, method: &str, args: &[Value]) -> MustardResult<(Value, Value)> {
89
+ let callback = args.first().cloned().unwrap_or(Value::Undefined);
90
+ if !is_callable(&callback) {
91
+ return Err(MustardError::runtime(format!(
92
+ "TypeError: {method} expects a callable callback",
93
+ )));
94
+ }
95
+ let this_arg = args.get(1).cloned().unwrap_or(Value::Undefined);
96
+ Ok((callback, this_arg))
97
+ }
98
+
99
+ fn call_collection_callback(
100
+ &mut self,
101
+ method: &str,
102
+ callback: Value,
103
+ this_arg: Value,
104
+ args: &[Value],
105
+ ) -> MustardResult<Value> {
106
+ let host_suspension_message =
107
+ format!("TypeError: {method} does not support synchronous host suspensions");
108
+ let unsettled_message = format!("synchronous {method} callback did not settle");
109
+ self.call_callback(
110
+ callback,
111
+ this_arg,
112
+ args,
113
+ CallbackCallOptions {
114
+ non_callable_message: "TypeError: collection callback is not callable",
115
+ host_suspension_message: &host_suspension_message,
116
+ unsettled_message: &unsettled_message,
117
+ allow_host_suspension: false,
118
+ allow_pending_promise_result: false,
119
+ },
120
+ )
121
+ }
122
+
123
+ pub(crate) fn call_iterator_next(&mut self, this_value: Value) -> MustardResult<Value> {
124
+ let iterator = self.iterator_receiver(this_value, "next")?;
125
+ let (value, done) = self.iterator_next(Value::Iterator(iterator))?;
126
+ let result = self.insert_object(
127
+ IndexMap::from([
128
+ ("value".to_string(), value),
129
+ ("done".to_string(), Value::Bool(done)),
130
+ ]),
131
+ ObjectKind::Plain,
132
+ )?;
133
+ Ok(Value::Object(result))
134
+ }
135
+
136
+ fn map_get(&self, map: MapKey, key: &Value) -> MustardResult<Option<MapEntry>> {
137
+ let normalized = canonicalize_collection_key(key.clone());
138
+ Ok(self
139
+ .maps
140
+ .get(map)
141
+ .ok_or_else(|| MustardError::runtime("map missing"))?
142
+ .entries
143
+ .iter()
144
+ .find(|entry| same_value_zero(&entry.key, &normalized))
145
+ .cloned())
146
+ }
147
+
148
+ fn map_set(&mut self, map: MapKey, key: Value, value: Value) -> MustardResult<()> {
149
+ let key = canonicalize_collection_key(key);
150
+ {
151
+ let entries = &mut self
152
+ .maps
153
+ .get_mut(map)
154
+ .ok_or_else(|| MustardError::runtime("map missing"))?
155
+ .entries;
156
+ if let Some(entry) = entries
157
+ .iter_mut()
158
+ .find(|entry| same_value_zero(&entry.key, &key))
159
+ {
160
+ entry.value = value;
161
+ } else {
162
+ entries.push(MapEntry { key, value });
163
+ }
164
+ }
165
+ self.refresh_map_accounting(map)
166
+ }
167
+
168
+ fn adjust_map_iterators_after_delete(&mut self, map: MapKey, removed_index: usize) {
169
+ let iterator_keys: Vec<_> = self
170
+ .iterators
171
+ .iter()
172
+ .filter_map(|(key, iterator)| match &iterator.state {
173
+ IteratorState::MapEntries(state)
174
+ | IteratorState::MapKeys(state)
175
+ | IteratorState::MapValues(state)
176
+ if state.map == map && removed_index < state.next_index =>
177
+ {
178
+ Some(key)
179
+ }
180
+ _ => None,
181
+ })
182
+ .collect();
183
+ for key in iterator_keys {
184
+ if let Some(iterator) = self.iterators.get_mut(key) {
185
+ match &mut iterator.state {
186
+ IteratorState::MapEntries(state)
187
+ | IteratorState::MapKeys(state)
188
+ | IteratorState::MapValues(state) => state.next_index -= 1,
189
+ _ => unreachable!("filtered iterator kind changed unexpectedly"),
190
+ }
191
+ }
192
+ }
193
+ }
194
+
195
+ fn reset_map_iterators_after_clear(&mut self, map: MapKey) {
196
+ let iterator_keys: Vec<_> = self
197
+ .iterators
198
+ .iter()
199
+ .filter_map(|(key, iterator)| match &iterator.state {
200
+ IteratorState::MapEntries(state)
201
+ | IteratorState::MapKeys(state)
202
+ | IteratorState::MapValues(state)
203
+ if state.map == map =>
204
+ {
205
+ Some(key)
206
+ }
207
+ _ => None,
208
+ })
209
+ .collect();
210
+ for key in iterator_keys {
211
+ if let Some(iterator) = self.iterators.get_mut(key) {
212
+ match &mut iterator.state {
213
+ IteratorState::MapEntries(state)
214
+ | IteratorState::MapKeys(state)
215
+ | IteratorState::MapValues(state) => state.next_index = 0,
216
+ _ => unreachable!("filtered iterator kind changed unexpectedly"),
217
+ }
218
+ }
219
+ }
220
+ }
221
+
222
+ fn map_delete(&mut self, map: MapKey, key: &Value) -> MustardResult<bool> {
223
+ let normalized = canonicalize_collection_key(key.clone());
224
+ let removed_index = {
225
+ let entries = &mut self
226
+ .maps
227
+ .get_mut(map)
228
+ .ok_or_else(|| MustardError::runtime("map missing"))?
229
+ .entries;
230
+ if let Some(index) = entries
231
+ .iter()
232
+ .position(|entry| same_value_zero(&entry.key, &normalized))
233
+ {
234
+ entries.remove(index);
235
+ Some(index)
236
+ } else {
237
+ None
238
+ }
239
+ };
240
+ if let Some(index) = removed_index {
241
+ self.adjust_map_iterators_after_delete(map, index);
242
+ self.refresh_map_accounting(map)?;
243
+ return Ok(true);
244
+ }
245
+ Ok(false)
246
+ }
247
+
248
+ fn map_clear(&mut self, map: MapKey) -> MustardResult<()> {
249
+ self.maps
250
+ .get_mut(map)
251
+ .ok_or_else(|| MustardError::runtime("map missing"))?
252
+ .entries
253
+ .clear();
254
+ self.reset_map_iterators_after_clear(map);
255
+ self.refresh_map_accounting(map)
256
+ }
257
+
258
+ fn set_add(&mut self, set: SetKey, value: Value) -> MustardResult<()> {
259
+ let value = canonicalize_collection_key(value);
260
+ {
261
+ let entries = &mut self
262
+ .sets
263
+ .get_mut(set)
264
+ .ok_or_else(|| MustardError::runtime("set missing"))?
265
+ .entries;
266
+ if !entries.iter().any(|entry| same_value_zero(entry, &value)) {
267
+ entries.push(value);
268
+ }
269
+ }
270
+ self.refresh_set_accounting(set)
271
+ }
272
+
273
+ fn adjust_set_iterators_after_delete(&mut self, set: SetKey, removed_index: usize) {
274
+ let iterator_keys: Vec<_> = self
275
+ .iterators
276
+ .iter()
277
+ .filter_map(|(key, iterator)| match &iterator.state {
278
+ IteratorState::SetEntries(state) | IteratorState::SetValues(state)
279
+ if state.set == set && removed_index < state.next_index =>
280
+ {
281
+ Some(key)
282
+ }
283
+ _ => None,
284
+ })
285
+ .collect();
286
+ for key in iterator_keys {
287
+ if let Some(iterator) = self.iterators.get_mut(key) {
288
+ match &mut iterator.state {
289
+ IteratorState::SetEntries(state) | IteratorState::SetValues(state) => {
290
+ state.next_index -= 1
291
+ }
292
+ _ => unreachable!("filtered iterator kind changed unexpectedly"),
293
+ }
294
+ }
295
+ }
296
+ }
297
+
298
+ fn reset_set_iterators_after_clear(&mut self, set: SetKey) {
299
+ let iterator_keys: Vec<_> = self
300
+ .iterators
301
+ .iter()
302
+ .filter_map(|(key, iterator)| match &iterator.state {
303
+ IteratorState::SetEntries(state) | IteratorState::SetValues(state)
304
+ if state.set == set =>
305
+ {
306
+ Some(key)
307
+ }
308
+ _ => None,
309
+ })
310
+ .collect();
311
+ for key in iterator_keys {
312
+ if let Some(iterator) = self.iterators.get_mut(key) {
313
+ match &mut iterator.state {
314
+ IteratorState::SetEntries(state) | IteratorState::SetValues(state) => {
315
+ state.next_index = 0
316
+ }
317
+ _ => unreachable!("filtered iterator kind changed unexpectedly"),
318
+ }
319
+ }
320
+ }
321
+ }
322
+
323
+ fn set_contains(&self, set: SetKey, value: &Value) -> MustardResult<bool> {
324
+ let normalized = canonicalize_collection_key(value.clone());
325
+ Ok(self
326
+ .sets
327
+ .get(set)
328
+ .ok_or_else(|| MustardError::runtime("set missing"))?
329
+ .entries
330
+ .iter()
331
+ .any(|entry| same_value_zero(entry, &normalized)))
332
+ }
333
+
334
+ fn set_delete(&mut self, set: SetKey, value: &Value) -> MustardResult<bool> {
335
+ let normalized = canonicalize_collection_key(value.clone());
336
+ let removed_index = {
337
+ let entries = &mut self
338
+ .sets
339
+ .get_mut(set)
340
+ .ok_or_else(|| MustardError::runtime("set missing"))?
341
+ .entries;
342
+ if let Some(index) = entries
343
+ .iter()
344
+ .position(|entry| same_value_zero(entry, &normalized))
345
+ {
346
+ entries.remove(index);
347
+ Some(index)
348
+ } else {
349
+ None
350
+ }
351
+ };
352
+ if let Some(index) = removed_index {
353
+ self.adjust_set_iterators_after_delete(set, index);
354
+ self.refresh_set_accounting(set)?;
355
+ return Ok(true);
356
+ }
357
+ Ok(false)
358
+ }
359
+
360
+ fn set_clear(&mut self, set: SetKey) -> MustardResult<()> {
361
+ self.sets
362
+ .get_mut(set)
363
+ .ok_or_else(|| MustardError::runtime("set missing"))?
364
+ .entries
365
+ .clear();
366
+ self.reset_set_iterators_after_clear(set);
367
+ self.refresh_set_accounting(set)
368
+ }
369
+
370
+ pub(crate) fn call_map_get(&self, this_value: Value, args: &[Value]) -> MustardResult<Value> {
371
+ let key = args.first().cloned().unwrap_or(Value::Undefined);
372
+ let map = self.map_receiver(this_value, "get")?;
373
+ Ok(self
374
+ .map_get(map, &key)?
375
+ .map(|entry| entry.value)
376
+ .unwrap_or(Value::Undefined))
377
+ }
378
+
379
+ pub(crate) fn call_map_set(
380
+ &mut self,
381
+ this_value: Value,
382
+ args: &[Value],
383
+ ) -> MustardResult<Value> {
384
+ let map = self.map_receiver(this_value, "set")?;
385
+ let key = args.first().cloned().unwrap_or(Value::Undefined);
386
+ let value = args.get(1).cloned().unwrap_or(Value::Undefined);
387
+ self.map_set(map, key, value)?;
388
+ Ok(Value::Map(map))
389
+ }
390
+
391
+ pub(crate) fn call_map_has(&self, this_value: Value, args: &[Value]) -> MustardResult<Value> {
392
+ let key = args.first().cloned().unwrap_or(Value::Undefined);
393
+ let map = self.map_receiver(this_value, "has")?;
394
+ Ok(Value::Bool(self.map_get(map, &key)?.is_some()))
395
+ }
396
+
397
+ pub(crate) fn call_map_delete(
398
+ &mut self,
399
+ this_value: Value,
400
+ args: &[Value],
401
+ ) -> MustardResult<Value> {
402
+ let key = args.first().cloned().unwrap_or(Value::Undefined);
403
+ let map = self.map_receiver(this_value, "delete")?;
404
+ Ok(Value::Bool(self.map_delete(map, &key)?))
405
+ }
406
+
407
+ pub(crate) fn call_map_clear(&mut self, this_value: Value) -> MustardResult<Value> {
408
+ let map = self.map_receiver(this_value, "clear")?;
409
+ self.map_clear(map)?;
410
+ Ok(Value::Undefined)
411
+ }
412
+
413
+ pub(crate) fn call_map_entries(&mut self, this_value: Value) -> MustardResult<Value> {
414
+ let map = self.map_receiver(this_value, "entries")?;
415
+ Ok(Value::Iterator(self.insert_iterator(
416
+ IteratorState::MapEntries(MapIteratorState { map, next_index: 0 }),
417
+ )?))
418
+ }
419
+
420
+ pub(crate) fn call_map_keys(&mut self, this_value: Value) -> MustardResult<Value> {
421
+ let map = self.map_receiver(this_value, "keys")?;
422
+ Ok(Value::Iterator(self.insert_iterator(
423
+ IteratorState::MapKeys(MapIteratorState { map, next_index: 0 }),
424
+ )?))
425
+ }
426
+
427
+ pub(crate) fn call_map_values(&mut self, this_value: Value) -> MustardResult<Value> {
428
+ let map = self.map_receiver(this_value, "values")?;
429
+ Ok(Value::Iterator(self.insert_iterator(
430
+ IteratorState::MapValues(MapIteratorState { map, next_index: 0 }),
431
+ )?))
432
+ }
433
+
434
+ pub(crate) fn call_map_for_each(
435
+ &mut self,
436
+ this_value: Value,
437
+ args: &[Value],
438
+ ) -> MustardResult<Value> {
439
+ let map = self.map_receiver(this_value, "forEach")?;
440
+ let (callback, this_arg) = self.collection_callback("Map.prototype.forEach", args)?;
441
+ let mut index = 0usize;
442
+ while index
443
+ < self
444
+ .maps
445
+ .get(map)
446
+ .ok_or_else(|| MustardError::runtime("map missing"))?
447
+ .entries
448
+ .len()
449
+ {
450
+ self.charge_native_helper_work(1)?;
451
+ if let Some(entry) = self
452
+ .maps
453
+ .get(map)
454
+ .ok_or_else(|| MustardError::runtime("map missing"))?
455
+ .entries
456
+ .get(index)
457
+ .cloned()
458
+ {
459
+ self.with_temporary_roots(
460
+ &[Value::Map(map), callback.clone(), this_arg.clone()],
461
+ |runtime| {
462
+ runtime.call_collection_callback(
463
+ "Map.prototype.forEach",
464
+ callback.clone(),
465
+ this_arg.clone(),
466
+ &[entry.value, entry.key, Value::Map(map)],
467
+ )?;
468
+ Ok(())
469
+ },
470
+ )?;
471
+ }
472
+ index += 1;
473
+ }
474
+ Ok(Value::Undefined)
475
+ }
476
+
477
+ pub(crate) fn call_set_add(
478
+ &mut self,
479
+ this_value: Value,
480
+ args: &[Value],
481
+ ) -> MustardResult<Value> {
482
+ let set = self.set_receiver(this_value, "add")?;
483
+ let value = args.first().cloned().unwrap_or(Value::Undefined);
484
+ self.set_add(set, value)?;
485
+ Ok(Value::Set(set))
486
+ }
487
+
488
+ pub(crate) fn call_set_has(&self, this_value: Value, args: &[Value]) -> MustardResult<Value> {
489
+ let value = args.first().cloned().unwrap_or(Value::Undefined);
490
+ let set = self.set_receiver(this_value, "has")?;
491
+ Ok(Value::Bool(self.set_contains(set, &value)?))
492
+ }
493
+
494
+ pub(crate) fn call_set_delete(
495
+ &mut self,
496
+ this_value: Value,
497
+ args: &[Value],
498
+ ) -> MustardResult<Value> {
499
+ let value = args.first().cloned().unwrap_or(Value::Undefined);
500
+ let set = self.set_receiver(this_value, "delete")?;
501
+ Ok(Value::Bool(self.set_delete(set, &value)?))
502
+ }
503
+
504
+ pub(crate) fn call_set_clear(&mut self, this_value: Value) -> MustardResult<Value> {
505
+ let set = self.set_receiver(this_value, "clear")?;
506
+ self.set_clear(set)?;
507
+ Ok(Value::Undefined)
508
+ }
509
+
510
+ pub(crate) fn call_set_entries(&mut self, this_value: Value) -> MustardResult<Value> {
511
+ let set = self.set_receiver(this_value, "entries")?;
512
+ Ok(Value::Iterator(self.insert_iterator(
513
+ IteratorState::SetEntries(SetIteratorState { set, next_index: 0 }),
514
+ )?))
515
+ }
516
+
517
+ pub(crate) fn call_set_keys(&mut self, this_value: Value) -> MustardResult<Value> {
518
+ let set = self.set_receiver(this_value, "keys")?;
519
+ Ok(Value::Iterator(self.insert_iterator(
520
+ IteratorState::SetValues(SetIteratorState { set, next_index: 0 }),
521
+ )?))
522
+ }
523
+
524
+ pub(crate) fn call_set_values(&mut self, this_value: Value) -> MustardResult<Value> {
525
+ let set = self.set_receiver(this_value, "values")?;
526
+ Ok(Value::Iterator(self.insert_iterator(
527
+ IteratorState::SetValues(SetIteratorState { set, next_index: 0 }),
528
+ )?))
529
+ }
530
+
531
+ pub(crate) fn call_set_for_each(
532
+ &mut self,
533
+ this_value: Value,
534
+ args: &[Value],
535
+ ) -> MustardResult<Value> {
536
+ let set = self.set_receiver(this_value, "forEach")?;
537
+ let (callback, this_arg) = self.collection_callback("Set.prototype.forEach", args)?;
538
+ let mut index = 0usize;
539
+ while index
540
+ < self
541
+ .sets
542
+ .get(set)
543
+ .ok_or_else(|| MustardError::runtime("set missing"))?
544
+ .entries
545
+ .len()
546
+ {
547
+ self.charge_native_helper_work(1)?;
548
+ if let Some(value) = self
549
+ .sets
550
+ .get(set)
551
+ .ok_or_else(|| MustardError::runtime("set missing"))?
552
+ .entries
553
+ .get(index)
554
+ .cloned()
555
+ {
556
+ self.with_temporary_roots(
557
+ &[Value::Set(set), callback.clone(), this_arg.clone()],
558
+ |runtime| {
559
+ runtime.call_collection_callback(
560
+ "Set.prototype.forEach",
561
+ callback.clone(),
562
+ this_arg.clone(),
563
+ &[value.clone(), value, Value::Set(set)],
564
+ )?;
565
+ Ok(())
566
+ },
567
+ )?;
568
+ }
569
+ index += 1;
570
+ }
571
+ Ok(Value::Undefined)
572
+ }
573
+ }