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.
- package/README.md +65 -22
- package/SECURITY.md +1 -1
- package/dist/index.js +2 -0
- package/dist/lib/executor.js +16 -1
- package/dist/lib/policy.js +301 -22
- package/dist/lib/progress.js +499 -113
- package/dist/lib/runtime.js +109 -40
- package/dist/lib/structured.js +327 -11
- package/dist/native-loader.js +11 -12
- package/index.d.ts +54 -6
- package/mustard.d.ts +23 -1
- package/package.json +34 -25
- package/Cargo.lock +0 -1579
- package/Cargo.toml +0 -40
- package/crates/mustard/Cargo.toml +0 -31
- package/crates/mustard/src/cancellation.rs +0 -28
- package/crates/mustard/src/diagnostic.rs +0 -145
- package/crates/mustard/src/ir.rs +0 -435
- package/crates/mustard/src/lib.rs +0 -21
- package/crates/mustard/src/limits.rs +0 -22
- package/crates/mustard/src/parser/expressions.rs +0 -723
- package/crates/mustard/src/parser/mod.rs +0 -115
- package/crates/mustard/src/parser/operators.rs +0 -105
- package/crates/mustard/src/parser/patterns.rs +0 -123
- package/crates/mustard/src/parser/scope.rs +0 -107
- package/crates/mustard/src/parser/statements.rs +0 -298
- package/crates/mustard/src/parser/tests/acceptance.rs +0 -339
- package/crates/mustard/src/parser/tests/mod.rs +0 -2
- package/crates/mustard/src/parser/tests/rejections.rs +0 -107
- package/crates/mustard/src/runtime/accounting.rs +0 -613
- package/crates/mustard/src/runtime/api.rs +0 -192
- package/crates/mustard/src/runtime/async_runtime/mod.rs +0 -5
- package/crates/mustard/src/runtime/async_runtime/promises.rs +0 -246
- package/crates/mustard/src/runtime/async_runtime/reactions.rs +0 -400
- package/crates/mustard/src/runtime/async_runtime/scheduler.rs +0 -224
- package/crates/mustard/src/runtime/builtins/arrays.rs +0 -1205
- package/crates/mustard/src/runtime/builtins/collections.rs +0 -573
- package/crates/mustard/src/runtime/builtins/install.rs +0 -501
- package/crates/mustard/src/runtime/builtins/intl.rs +0 -553
- package/crates/mustard/src/runtime/builtins/mod.rs +0 -25
- package/crates/mustard/src/runtime/builtins/objects.rs +0 -405
- package/crates/mustard/src/runtime/builtins/primitives.rs +0 -859
- package/crates/mustard/src/runtime/builtins/promises.rs +0 -335
- package/crates/mustard/src/runtime/builtins/regexp.rs +0 -356
- package/crates/mustard/src/runtime/builtins/strings.rs +0 -803
- package/crates/mustard/src/runtime/builtins/support.rs +0 -561
- package/crates/mustard/src/runtime/bytecode.rs +0 -123
- package/crates/mustard/src/runtime/compiler/assignments.rs +0 -690
- package/crates/mustard/src/runtime/compiler/bindings.rs +0 -92
- package/crates/mustard/src/runtime/compiler/context.rs +0 -46
- package/crates/mustard/src/runtime/compiler/control.rs +0 -342
- package/crates/mustard/src/runtime/compiler/expressions.rs +0 -372
- package/crates/mustard/src/runtime/compiler/mod.rs +0 -173
- package/crates/mustard/src/runtime/compiler/statements.rs +0 -459
- package/crates/mustard/src/runtime/conversions/boundary.rs +0 -293
- package/crates/mustard/src/runtime/conversions/coercions.rs +0 -217
- package/crates/mustard/src/runtime/conversions/errors.rs +0 -118
- package/crates/mustard/src/runtime/conversions/mod.rs +0 -14
- package/crates/mustard/src/runtime/conversions/operators.rs +0 -334
- package/crates/mustard/src/runtime/env.rs +0 -355
- package/crates/mustard/src/runtime/exceptions.rs +0 -377
- package/crates/mustard/src/runtime/gc.rs +0 -595
- package/crates/mustard/src/runtime/mod.rs +0 -318
- package/crates/mustard/src/runtime/properties.rs +0 -1762
- package/crates/mustard/src/runtime/serialization.rs +0 -127
- package/crates/mustard/src/runtime/shared.rs +0 -108
- package/crates/mustard/src/runtime/snapshot_validation_tests.rs +0 -93
- package/crates/mustard/src/runtime/state.rs +0 -652
- package/crates/mustard/src/runtime/tests/async_host.rs +0 -104
- package/crates/mustard/src/runtime/tests/collections.rs +0 -50
- package/crates/mustard/src/runtime/tests/diagnostics.rs +0 -36
- package/crates/mustard/src/runtime/tests/exceptions.rs +0 -122
- package/crates/mustard/src/runtime/tests/execution.rs +0 -553
- package/crates/mustard/src/runtime/tests/gc.rs +0 -533
- package/crates/mustard/src/runtime/tests/mod.rs +0 -56
- package/crates/mustard/src/runtime/tests/serialization.rs +0 -170
- package/crates/mustard/src/runtime/validation/bytecode.rs +0 -484
- package/crates/mustard/src/runtime/validation/mod.rs +0 -14
- package/crates/mustard/src/runtime/validation/policy.rs +0 -94
- package/crates/mustard/src/runtime/validation/snapshot.rs +0 -406
- package/crates/mustard/src/runtime/validation/walk.rs +0 -206
- package/crates/mustard/src/runtime/vm.rs +0 -1016
- package/crates/mustard/src/span.rs +0 -22
- package/crates/mustard/src/structured.rs +0 -107
- package/crates/mustard-bridge/Cargo.toml +0 -17
- package/crates/mustard-bridge/src/codec.rs +0 -46
- package/crates/mustard-bridge/src/dto.rs +0 -99
- package/crates/mustard-bridge/src/lib.rs +0 -12
- package/crates/mustard-bridge/src/operations.rs +0 -142
- package/crates/mustard-node/Cargo.toml +0 -24
- package/crates/mustard-node/build.rs +0 -3
- package/crates/mustard-node/src/lib.rs +0 -236
- package/crates/mustard-sidecar/Cargo.toml +0 -21
- package/crates/mustard-sidecar/src/lib.rs +0 -134
- package/crates/mustard-sidecar/src/main.rs +0 -36
- package/dist/install.js +0 -117
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
use super::*;
|
|
2
|
-
|
|
3
|
-
pub(in crate::runtime) fn validate_snapshot_policy(
|
|
4
|
-
runtime: &Runtime,
|
|
5
|
-
policy: &SnapshotPolicy,
|
|
6
|
-
) -> MustardResult<()> {
|
|
7
|
-
let allowed = policy
|
|
8
|
-
.capabilities
|
|
9
|
-
.iter()
|
|
10
|
-
.cloned()
|
|
11
|
-
.collect::<HashSet<String>>();
|
|
12
|
-
|
|
13
|
-
walk::walk_heap_values(runtime, &mut |value| {
|
|
14
|
-
validate_runtime_host_capability(value, &allowed)
|
|
15
|
-
})?;
|
|
16
|
-
for frame in &runtime.frames {
|
|
17
|
-
validate_frame_host_capabilities(frame, &allowed)?;
|
|
18
|
-
}
|
|
19
|
-
if let Some(root_result) = &runtime.root_result {
|
|
20
|
-
validate_runtime_host_capability(root_result, &allowed)?;
|
|
21
|
-
}
|
|
22
|
-
for request in &runtime.pending_host_calls {
|
|
23
|
-
validate_pending_host_call_capability(request, &allowed)?;
|
|
24
|
-
}
|
|
25
|
-
if let Some(request) = &runtime.suspended_host_call {
|
|
26
|
-
validate_pending_host_call_capability(request, &allowed)?;
|
|
27
|
-
}
|
|
28
|
-
for promise in runtime.promises.values() {
|
|
29
|
-
walk::walk_promise_values(promise, &mut |value| {
|
|
30
|
-
validate_runtime_host_capability(value, &allowed)
|
|
31
|
-
})?;
|
|
32
|
-
for continuation in &promise.awaiters {
|
|
33
|
-
walk::walk_continuation_frames(continuation, &mut |frame| {
|
|
34
|
-
validate_frame_host_capabilities(frame, &allowed)
|
|
35
|
-
})?;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
for microtask in &runtime.microtasks {
|
|
39
|
-
walk::walk_microtask_values(
|
|
40
|
-
microtask,
|
|
41
|
-
&mut |frame| validate_frame_host_capabilities(frame, &allowed),
|
|
42
|
-
&mut |value| validate_runtime_host_capability(value, &allowed),
|
|
43
|
-
)?;
|
|
44
|
-
}
|
|
45
|
-
if let Some(exception) = &runtime.pending_internal_exception {
|
|
46
|
-
validate_promise_rejection_host_capabilities(exception, &allowed)?;
|
|
47
|
-
}
|
|
48
|
-
Ok(())
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
fn validate_runtime_host_capability(value: &Value, allowed: &HashSet<String>) -> MustardResult<()> {
|
|
52
|
-
match value {
|
|
53
|
-
Value::HostFunction(capability) if !allowed.contains(capability) => {
|
|
54
|
-
Err(MustardError::Message {
|
|
55
|
-
kind: DiagnosticKind::Serialization,
|
|
56
|
-
message: format!("snapshot policy rejected unauthorized capability `{capability}`"),
|
|
57
|
-
span: None,
|
|
58
|
-
traceback: Vec::new(),
|
|
59
|
-
})
|
|
60
|
-
}
|
|
61
|
-
_ => Ok(()),
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
fn validate_pending_host_call_capability(
|
|
66
|
-
request: &PendingHostCall,
|
|
67
|
-
allowed: &HashSet<String>,
|
|
68
|
-
) -> MustardResult<()> {
|
|
69
|
-
if !allowed.contains(&request.capability) {
|
|
70
|
-
return Err(MustardError::Message {
|
|
71
|
-
kind: DiagnosticKind::Serialization,
|
|
72
|
-
message: format!(
|
|
73
|
-
"snapshot policy rejected unauthorized capability `{}`",
|
|
74
|
-
request.capability
|
|
75
|
-
),
|
|
76
|
-
span: None,
|
|
77
|
-
traceback: Vec::new(),
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
Ok(())
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
fn validate_frame_host_capabilities(frame: &Frame, allowed: &HashSet<String>) -> MustardResult<()> {
|
|
84
|
-
walk::walk_frame_values(frame, &mut |value| {
|
|
85
|
-
validate_runtime_host_capability(value, allowed)
|
|
86
|
-
})
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
fn validate_promise_rejection_host_capabilities(
|
|
90
|
-
rejection: &PromiseRejection,
|
|
91
|
-
allowed: &HashSet<String>,
|
|
92
|
-
) -> MustardResult<()> {
|
|
93
|
-
validate_runtime_host_capability(&rejection.value, allowed)
|
|
94
|
-
}
|
|
@@ -1,406 +0,0 @@
|
|
|
1
|
-
use super::*;
|
|
2
|
-
|
|
3
|
-
pub(in crate::runtime) fn validate_snapshot(snapshot: &ExecutionSnapshot) -> MustardResult<()> {
|
|
4
|
-
let runtime = &snapshot.runtime;
|
|
5
|
-
validate_bytecode_program(&runtime.program)?;
|
|
6
|
-
if runtime.envs.get(runtime.globals).is_none() {
|
|
7
|
-
return Err(snapshot_error("missing globals environment"));
|
|
8
|
-
}
|
|
9
|
-
if runtime.frames.len() > runtime.limits.call_depth_limit {
|
|
10
|
-
return Err(limit_error("call depth limit exceeded"));
|
|
11
|
-
}
|
|
12
|
-
if runtime.frames.is_empty()
|
|
13
|
-
&& runtime.suspended_host_call.is_none()
|
|
14
|
-
&& runtime.root_result.is_none()
|
|
15
|
-
&& runtime.microtasks.is_empty()
|
|
16
|
-
{
|
|
17
|
-
return Err(snapshot_error(
|
|
18
|
-
"suspended runtime has no frames or async state",
|
|
19
|
-
));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
validate_envs(runtime)?;
|
|
23
|
-
validate_closures(runtime)?;
|
|
24
|
-
validate_builtin_function_objects(runtime)?;
|
|
25
|
-
for frame in &runtime.frames {
|
|
26
|
-
validate_frame(runtime, frame)?;
|
|
27
|
-
walk::walk_frame_values(frame, &mut |value| validate_runtime_value(runtime, value))?;
|
|
28
|
-
}
|
|
29
|
-
walk::walk_heap_values(runtime, &mut |value| validate_runtime_value(runtime, value))?;
|
|
30
|
-
validate_iterators(runtime)?;
|
|
31
|
-
if let Some(root_result) = &runtime.root_result {
|
|
32
|
-
validate_runtime_value(runtime, root_result)?;
|
|
33
|
-
}
|
|
34
|
-
for request in &runtime.pending_host_calls {
|
|
35
|
-
validate_pending_host_call_snapshot(runtime, request)?;
|
|
36
|
-
}
|
|
37
|
-
if let Some(request) = &runtime.suspended_host_call {
|
|
38
|
-
validate_pending_host_call_snapshot(runtime, request)?;
|
|
39
|
-
}
|
|
40
|
-
for (promise_key, promise) in &runtime.promises {
|
|
41
|
-
validate_promise_snapshot(runtime, promise_key, promise)?;
|
|
42
|
-
walk::walk_promise_values(promise, &mut |value| validate_runtime_value(runtime, value))?;
|
|
43
|
-
for continuation in &promise.awaiters {
|
|
44
|
-
walk::walk_continuation_frames(continuation, &mut |frame| {
|
|
45
|
-
validate_frame(runtime, frame)?;
|
|
46
|
-
walk::walk_frame_values(frame, &mut |value| validate_runtime_value(runtime, value))
|
|
47
|
-
})?;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
for microtask in &runtime.microtasks {
|
|
51
|
-
walk::walk_microtask_values(
|
|
52
|
-
microtask,
|
|
53
|
-
&mut |frame| {
|
|
54
|
-
validate_frame(runtime, frame)?;
|
|
55
|
-
walk::walk_frame_values(frame, &mut |value| validate_runtime_value(runtime, value))
|
|
56
|
-
},
|
|
57
|
-
&mut |value| validate_runtime_value(runtime, value),
|
|
58
|
-
)?;
|
|
59
|
-
}
|
|
60
|
-
if let Some(exception) = &runtime.pending_internal_exception {
|
|
61
|
-
validate_runtime_value(runtime, &exception.value)?;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
Ok(())
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
fn snapshot_error(message: impl Into<String>) -> MustardError {
|
|
68
|
-
MustardError::Message {
|
|
69
|
-
kind: DiagnosticKind::Serialization,
|
|
70
|
-
message: format!("snapshot validation failed: {}", message.into()),
|
|
71
|
-
span: None,
|
|
72
|
-
traceback: Vec::new(),
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
fn validate_envs(runtime: &Runtime) -> MustardResult<()> {
|
|
77
|
-
for (env_key, env) in &runtime.envs {
|
|
78
|
-
if let Some(parent) = env.parent
|
|
79
|
-
&& runtime.envs.get(parent).is_none()
|
|
80
|
-
{
|
|
81
|
-
return Err(snapshot_error(format!(
|
|
82
|
-
"environment {:?} references missing parent {:?}",
|
|
83
|
-
env_key, parent
|
|
84
|
-
)));
|
|
85
|
-
}
|
|
86
|
-
for cell in env.bindings.values() {
|
|
87
|
-
if runtime.cells.get(*cell).is_none() {
|
|
88
|
-
return Err(snapshot_error(format!(
|
|
89
|
-
"environment {:?} references missing cell {:?}",
|
|
90
|
-
env_key, cell
|
|
91
|
-
)));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
Ok(())
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
fn validate_closures(runtime: &Runtime) -> MustardResult<()> {
|
|
99
|
-
for (closure_key, closure) in &runtime.closures {
|
|
100
|
-
if closure.function_id >= runtime.program.functions.len() {
|
|
101
|
-
return Err(snapshot_error(format!(
|
|
102
|
-
"closure {:?} references missing function {}",
|
|
103
|
-
closure_key, closure.function_id
|
|
104
|
-
)));
|
|
105
|
-
}
|
|
106
|
-
if runtime.envs.get(closure.env).is_none() {
|
|
107
|
-
return Err(snapshot_error(format!(
|
|
108
|
-
"closure {:?} references missing environment {:?}",
|
|
109
|
-
closure_key, closure.env
|
|
110
|
-
)));
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
Ok(())
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
fn validate_builtin_function_objects(runtime: &Runtime) -> MustardResult<()> {
|
|
117
|
-
for (function, object) in &runtime.builtin_prototypes {
|
|
118
|
-
if runtime.objects.get(*object).is_none() {
|
|
119
|
-
return Err(snapshot_error(format!(
|
|
120
|
-
"builtin prototype {:?} references missing object {:?}",
|
|
121
|
-
function, object
|
|
122
|
-
)));
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
for (function, object) in &runtime.builtin_function_objects {
|
|
126
|
-
if runtime.objects.get(*object).is_none() {
|
|
127
|
-
return Err(snapshot_error(format!(
|
|
128
|
-
"builtin function object {:?} references missing object {:?}",
|
|
129
|
-
function, object
|
|
130
|
-
)));
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
for (capability, object) in &runtime.host_function_objects {
|
|
134
|
-
if runtime.objects.get(*object).is_none() {
|
|
135
|
-
return Err(snapshot_error(format!(
|
|
136
|
-
"host function object `{capability}` references missing object {:?}",
|
|
137
|
-
object
|
|
138
|
-
)));
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
Ok(())
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
fn validate_frame(runtime: &Runtime, frame: &Frame) -> MustardResult<()> {
|
|
145
|
-
let Some(function) = runtime.program.functions.get(frame.function_id) else {
|
|
146
|
-
return Err(snapshot_error(format!(
|
|
147
|
-
"frame references missing function {}",
|
|
148
|
-
frame.function_id
|
|
149
|
-
)));
|
|
150
|
-
};
|
|
151
|
-
if frame.ip >= function.code.len() {
|
|
152
|
-
return Err(snapshot_error(format!(
|
|
153
|
-
"frame instruction pointer {} is out of range for function {}",
|
|
154
|
-
frame.ip, frame.function_id
|
|
155
|
-
)));
|
|
156
|
-
}
|
|
157
|
-
if runtime.envs.get(frame.env).is_none() {
|
|
158
|
-
return Err(snapshot_error(format!(
|
|
159
|
-
"frame references missing environment {:?}",
|
|
160
|
-
frame.env
|
|
161
|
-
)));
|
|
162
|
-
}
|
|
163
|
-
for env in &frame.scope_stack {
|
|
164
|
-
if runtime.envs.get(*env).is_none() {
|
|
165
|
-
return Err(snapshot_error(format!(
|
|
166
|
-
"frame scope stack references missing environment {:?}",
|
|
167
|
-
env
|
|
168
|
-
)));
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
for handler in &frame.handlers {
|
|
172
|
-
if let Some(catch) = handler.catch
|
|
173
|
-
&& catch >= function.code.len()
|
|
174
|
-
{
|
|
175
|
-
return Err(snapshot_error(format!(
|
|
176
|
-
"frame handler catch target {} is out of range for function {}",
|
|
177
|
-
catch, frame.function_id
|
|
178
|
-
)));
|
|
179
|
-
}
|
|
180
|
-
if let Some(finally) = handler.finally
|
|
181
|
-
&& finally >= function.code.len()
|
|
182
|
-
{
|
|
183
|
-
return Err(snapshot_error(format!(
|
|
184
|
-
"frame handler finally target {} is out of range for function {}",
|
|
185
|
-
finally, frame.function_id
|
|
186
|
-
)));
|
|
187
|
-
}
|
|
188
|
-
if runtime.envs.get(handler.env).is_none() {
|
|
189
|
-
return Err(snapshot_error(format!(
|
|
190
|
-
"frame handler references missing environment {:?}",
|
|
191
|
-
handler.env
|
|
192
|
-
)));
|
|
193
|
-
}
|
|
194
|
-
if handler.scope_stack_len > frame.scope_stack.len()
|
|
195
|
-
|| handler.stack_len > frame.stack.len()
|
|
196
|
-
{
|
|
197
|
-
return Err(snapshot_error(
|
|
198
|
-
"frame handler restore state exceeds the current frame state",
|
|
199
|
-
));
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
for completion in &frame.pending_completions {
|
|
203
|
-
match completion {
|
|
204
|
-
CompletionRecord::Jump {
|
|
205
|
-
target,
|
|
206
|
-
target_handler_depth,
|
|
207
|
-
target_scope_depth,
|
|
208
|
-
} => {
|
|
209
|
-
if *target >= function.code.len() {
|
|
210
|
-
return Err(snapshot_error(format!(
|
|
211
|
-
"pending jump target {} is out of range for function {}",
|
|
212
|
-
target, frame.function_id
|
|
213
|
-
)));
|
|
214
|
-
}
|
|
215
|
-
if *target_handler_depth > frame.handlers.len() {
|
|
216
|
-
return Err(snapshot_error(format!(
|
|
217
|
-
"pending jump targets handler depth {} but only {} handlers are active",
|
|
218
|
-
target_handler_depth,
|
|
219
|
-
frame.handlers.len()
|
|
220
|
-
)));
|
|
221
|
-
}
|
|
222
|
-
if *target_scope_depth > frame.scope_stack.len() {
|
|
223
|
-
return Err(snapshot_error(format!(
|
|
224
|
-
"pending jump targets scope depth {} but only {} scopes are active",
|
|
225
|
-
target_scope_depth,
|
|
226
|
-
frame.scope_stack.len()
|
|
227
|
-
)));
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
CompletionRecord::Return(value) | CompletionRecord::Throw(value) => {
|
|
231
|
-
validate_runtime_value(runtime, value)?;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
for active in &frame.active_finally {
|
|
236
|
-
if active.completion_index >= frame.pending_completions.len() {
|
|
237
|
-
return Err(snapshot_error(
|
|
238
|
-
"active finally references a missing completion",
|
|
239
|
-
));
|
|
240
|
-
}
|
|
241
|
-
if active.exit >= function.code.len() {
|
|
242
|
-
return Err(snapshot_error(format!(
|
|
243
|
-
"active finally exit target {} is out of range for function {}",
|
|
244
|
-
active.exit, frame.function_id
|
|
245
|
-
)));
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
Ok(())
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
fn validate_iterators(runtime: &Runtime) -> MustardResult<()> {
|
|
252
|
-
for iterator in runtime.iterators.values() {
|
|
253
|
-
match iterator.state {
|
|
254
|
-
IteratorState::Array(ref state)
|
|
255
|
-
| IteratorState::ArrayKeys(ref state)
|
|
256
|
-
| IteratorState::ArrayEntries(ref state) => {
|
|
257
|
-
if runtime.arrays.get(state.array).is_none() {
|
|
258
|
-
return Err(snapshot_error(format!(
|
|
259
|
-
"iterator references missing array {:?}",
|
|
260
|
-
state.array
|
|
261
|
-
)));
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
IteratorState::String(_) => {}
|
|
265
|
-
IteratorState::MapEntries(ref state)
|
|
266
|
-
| IteratorState::MapKeys(ref state)
|
|
267
|
-
| IteratorState::MapValues(ref state) => {
|
|
268
|
-
if runtime.maps.get(state.map).is_none() {
|
|
269
|
-
return Err(snapshot_error(format!(
|
|
270
|
-
"iterator references missing map {:?}",
|
|
271
|
-
state.map
|
|
272
|
-
)));
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
IteratorState::SetEntries(ref state) | IteratorState::SetValues(ref state) => {
|
|
276
|
-
if runtime.sets.get(state.set).is_none() {
|
|
277
|
-
return Err(snapshot_error(format!(
|
|
278
|
-
"iterator references missing set {:?}",
|
|
279
|
-
state.set
|
|
280
|
-
)));
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
Ok(())
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
fn validate_pending_host_call_snapshot(
|
|
289
|
-
runtime: &Runtime,
|
|
290
|
-
request: &PendingHostCall,
|
|
291
|
-
) -> MustardResult<()> {
|
|
292
|
-
if let Some(promise) = request.promise
|
|
293
|
-
&& runtime.promises.get(promise).is_none()
|
|
294
|
-
{
|
|
295
|
-
return Err(snapshot_error(
|
|
296
|
-
"pending host call references a missing promise",
|
|
297
|
-
));
|
|
298
|
-
}
|
|
299
|
-
Ok(())
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
fn validate_promise_snapshot(
|
|
303
|
-
runtime: &Runtime,
|
|
304
|
-
promise_key: PromiseKey,
|
|
305
|
-
promise: &PromiseObject,
|
|
306
|
-
) -> MustardResult<()> {
|
|
307
|
-
for dependent in &promise.dependents {
|
|
308
|
-
if runtime.promises.get(*dependent).is_none() {
|
|
309
|
-
return Err(snapshot_error(format!(
|
|
310
|
-
"promise {:?} references missing dependent {:?}",
|
|
311
|
-
promise_key, dependent
|
|
312
|
-
)));
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
for reaction in &promise.reactions {
|
|
316
|
-
match reaction {
|
|
317
|
-
PromiseReaction::Then { target, .. }
|
|
318
|
-
| PromiseReaction::Finally { target, .. }
|
|
319
|
-
| PromiseReaction::FinallyPassThrough { target, .. }
|
|
320
|
-
| PromiseReaction::Combinator { target, .. } => {
|
|
321
|
-
if runtime.promises.get(*target).is_none() {
|
|
322
|
-
return Err(snapshot_error(format!(
|
|
323
|
-
"promise {:?} reaction references missing target {:?}",
|
|
324
|
-
promise_key, target
|
|
325
|
-
)));
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
if let PromiseReaction::Combinator {
|
|
331
|
-
target,
|
|
332
|
-
index,
|
|
333
|
-
kind,
|
|
334
|
-
} = reaction
|
|
335
|
-
{
|
|
336
|
-
let target_promise = runtime.promises.get(*target).ok_or_else(|| {
|
|
337
|
-
snapshot_error(format!(
|
|
338
|
-
"promise {:?} combinator reaction references missing target {:?}",
|
|
339
|
-
promise_key, target
|
|
340
|
-
))
|
|
341
|
-
})?;
|
|
342
|
-
let Some(driver) = target_promise.driver.as_ref() else {
|
|
343
|
-
return Err(snapshot_error(format!(
|
|
344
|
-
"promise {:?} combinator target {:?} is missing driver state",
|
|
345
|
-
promise_key, target
|
|
346
|
-
)));
|
|
347
|
-
};
|
|
348
|
-
let len = match (kind, driver) {
|
|
349
|
-
(PromiseCombinatorKind::Race, _) => None,
|
|
350
|
-
(PromiseCombinatorKind::All, PromiseDriver::All { values, .. }) => {
|
|
351
|
-
Some(values.len())
|
|
352
|
-
}
|
|
353
|
-
(PromiseCombinatorKind::AllSettled, PromiseDriver::AllSettled { results, .. }) => {
|
|
354
|
-
Some(results.len())
|
|
355
|
-
}
|
|
356
|
-
(PromiseCombinatorKind::Any, PromiseDriver::Any { reasons, .. }) => {
|
|
357
|
-
Some(reasons.len())
|
|
358
|
-
}
|
|
359
|
-
_ => {
|
|
360
|
-
return Err(snapshot_error(format!(
|
|
361
|
-
"promise {:?} combinator reaction kind does not match target {:?} driver",
|
|
362
|
-
promise_key, target
|
|
363
|
-
)));
|
|
364
|
-
}
|
|
365
|
-
};
|
|
366
|
-
if let Some(len) = len
|
|
367
|
-
&& *index >= len
|
|
368
|
-
{
|
|
369
|
-
return Err(snapshot_error(format!(
|
|
370
|
-
"promise {:?} combinator index {} is out of range for target {:?}",
|
|
371
|
-
promise_key, index, target
|
|
372
|
-
)));
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
Ok(())
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
fn validate_runtime_value(runtime: &Runtime, value: &Value) -> MustardResult<()> {
|
|
380
|
-
match value {
|
|
381
|
-
Value::Object(object) if runtime.objects.get(*object).is_none() => Err(snapshot_error(
|
|
382
|
-
format!("value references missing object {:?}", object),
|
|
383
|
-
)),
|
|
384
|
-
Value::Array(array) if runtime.arrays.get(*array).is_none() => Err(snapshot_error(
|
|
385
|
-
format!("value references missing array {:?}", array),
|
|
386
|
-
)),
|
|
387
|
-
Value::Map(map) if runtime.maps.get(*map).is_none() => Err(snapshot_error(format!(
|
|
388
|
-
"value references missing map {:?}",
|
|
389
|
-
map
|
|
390
|
-
))),
|
|
391
|
-
Value::Set(set) if runtime.sets.get(*set).is_none() => Err(snapshot_error(format!(
|
|
392
|
-
"value references missing set {:?}",
|
|
393
|
-
set
|
|
394
|
-
))),
|
|
395
|
-
Value::Iterator(iterator) if runtime.iterators.get(*iterator).is_none() => Err(
|
|
396
|
-
snapshot_error(format!("value references missing iterator {:?}", iterator)),
|
|
397
|
-
),
|
|
398
|
-
Value::Closure(closure) if runtime.closures.get(*closure).is_none() => Err(snapshot_error(
|
|
399
|
-
format!("value references missing closure {:?}", closure),
|
|
400
|
-
)),
|
|
401
|
-
Value::Promise(promise) if runtime.promises.get(*promise).is_none() => Err(snapshot_error(
|
|
402
|
-
format!("value references missing promise {:?}", promise),
|
|
403
|
-
)),
|
|
404
|
-
_ => Ok(()),
|
|
405
|
-
}
|
|
406
|
-
}
|
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
use super::*;
|
|
2
|
-
|
|
3
|
-
pub(super) fn walk_heap_values<F>(runtime: &Runtime, visit: &mut F) -> MustardResult<()>
|
|
4
|
-
where
|
|
5
|
-
F: FnMut(&Value) -> MustardResult<()>,
|
|
6
|
-
{
|
|
7
|
-
for cell in runtime.cells.values() {
|
|
8
|
-
visit(&cell.value)?;
|
|
9
|
-
}
|
|
10
|
-
for object in runtime.objects.values() {
|
|
11
|
-
match &object.kind {
|
|
12
|
-
ObjectKind::FunctionPrototype(constructor) => visit(constructor)?,
|
|
13
|
-
ObjectKind::BoundFunction(bound) => {
|
|
14
|
-
visit(&bound.target)?;
|
|
15
|
-
visit(&bound.this_value)?;
|
|
16
|
-
for value in &bound.args {
|
|
17
|
-
visit(value)?;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
_ => {}
|
|
21
|
-
}
|
|
22
|
-
for value in object.properties.values() {
|
|
23
|
-
visit(value)?;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
for array in runtime.arrays.values() {
|
|
27
|
-
for value in array.elements.iter().flatten() {
|
|
28
|
-
visit(value)?;
|
|
29
|
-
}
|
|
30
|
-
for value in array.properties.values() {
|
|
31
|
-
visit(value)?;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
for map in runtime.maps.values() {
|
|
35
|
-
for entry in &map.entries {
|
|
36
|
-
visit(&entry.key)?;
|
|
37
|
-
visit(&entry.value)?;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
for set in runtime.sets.values() {
|
|
41
|
-
for value in &set.entries {
|
|
42
|
-
visit(value)?;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
for closure in runtime.closures.values() {
|
|
46
|
-
visit(&closure.this_value)?;
|
|
47
|
-
if let Some(prototype) = closure.prototype {
|
|
48
|
-
visit(&Value::Object(prototype))?;
|
|
49
|
-
}
|
|
50
|
-
for value in closure.properties.values() {
|
|
51
|
-
visit(value)?;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
Ok(())
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
pub(super) fn walk_frame_values<F>(frame: &Frame, visit: &mut F) -> MustardResult<()>
|
|
58
|
-
where
|
|
59
|
-
F: FnMut(&Value) -> MustardResult<()>,
|
|
60
|
-
{
|
|
61
|
-
for value in &frame.stack {
|
|
62
|
-
visit(value)?;
|
|
63
|
-
}
|
|
64
|
-
if let Some(value) = &frame.pending_exception {
|
|
65
|
-
visit(value)?;
|
|
66
|
-
}
|
|
67
|
-
for completion in &frame.pending_completions {
|
|
68
|
-
match completion {
|
|
69
|
-
CompletionRecord::Return(value) | CompletionRecord::Throw(value) => visit(value)?,
|
|
70
|
-
CompletionRecord::Jump { .. } => {}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
Ok(())
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
pub(super) fn walk_promise_values<F>(promise: &PromiseObject, visit: &mut F) -> MustardResult<()>
|
|
77
|
-
where
|
|
78
|
-
F: FnMut(&Value) -> MustardResult<()>,
|
|
79
|
-
{
|
|
80
|
-
match &promise.state {
|
|
81
|
-
PromiseState::Pending => {}
|
|
82
|
-
PromiseState::Fulfilled(value) => visit(value)?,
|
|
83
|
-
PromiseState::Rejected(rejection) => visit(&rejection.value)?,
|
|
84
|
-
}
|
|
85
|
-
for reaction in &promise.reactions {
|
|
86
|
-
match reaction {
|
|
87
|
-
PromiseReaction::Then {
|
|
88
|
-
on_fulfilled,
|
|
89
|
-
on_rejected,
|
|
90
|
-
..
|
|
91
|
-
} => {
|
|
92
|
-
if let Some(handler) = on_fulfilled {
|
|
93
|
-
visit(handler)?;
|
|
94
|
-
}
|
|
95
|
-
if let Some(handler) = on_rejected {
|
|
96
|
-
visit(handler)?;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
PromiseReaction::Finally { callback, .. } => {
|
|
100
|
-
if let Some(callback) = callback {
|
|
101
|
-
visit(callback)?;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
PromiseReaction::FinallyPassThrough {
|
|
105
|
-
original_outcome, ..
|
|
106
|
-
} => match original_outcome {
|
|
107
|
-
PromiseOutcome::Fulfilled(value) => visit(value)?,
|
|
108
|
-
PromiseOutcome::Rejected(rejection) => visit(&rejection.value)?,
|
|
109
|
-
},
|
|
110
|
-
PromiseReaction::Combinator { .. } => {}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if let Some(driver) = &promise.driver {
|
|
114
|
-
match driver {
|
|
115
|
-
PromiseDriver::Thenable { value } => visit(value)?,
|
|
116
|
-
PromiseDriver::All { values, .. } => {
|
|
117
|
-
for value in values.iter().flatten() {
|
|
118
|
-
visit(value)?;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
PromiseDriver::AllSettled { results, .. } => {
|
|
122
|
-
for result in results.iter().flatten() {
|
|
123
|
-
match result {
|
|
124
|
-
PromiseSettledResult::Fulfilled(value)
|
|
125
|
-
| PromiseSettledResult::Rejected(value) => visit(value)?,
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
PromiseDriver::Any { reasons, .. } => {
|
|
130
|
-
for value in reasons.iter().flatten() {
|
|
131
|
-
visit(value)?;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
Ok(())
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
pub(super) fn walk_continuation_frames<F>(
|
|
140
|
-
continuation: &AsyncContinuation,
|
|
141
|
-
visit_frame: &mut F,
|
|
142
|
-
) -> MustardResult<()>
|
|
143
|
-
where
|
|
144
|
-
F: FnMut(&Frame) -> MustardResult<()>,
|
|
145
|
-
{
|
|
146
|
-
for frame in &continuation.frames {
|
|
147
|
-
visit_frame(frame)?;
|
|
148
|
-
}
|
|
149
|
-
Ok(())
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
pub(super) fn walk_microtask_values<F, G>(
|
|
153
|
-
microtask: &MicrotaskJob,
|
|
154
|
-
visit_frame: &mut F,
|
|
155
|
-
visit_value: &mut G,
|
|
156
|
-
) -> MustardResult<()>
|
|
157
|
-
where
|
|
158
|
-
F: FnMut(&Frame) -> MustardResult<()>,
|
|
159
|
-
G: FnMut(&Value) -> MustardResult<()>,
|
|
160
|
-
{
|
|
161
|
-
match microtask {
|
|
162
|
-
MicrotaskJob::ResumeAsync {
|
|
163
|
-
continuation,
|
|
164
|
-
outcome,
|
|
165
|
-
} => {
|
|
166
|
-
walk_continuation_frames(continuation, visit_frame)?;
|
|
167
|
-
match outcome {
|
|
168
|
-
PromiseOutcome::Fulfilled(value) => visit_value(value)?,
|
|
169
|
-
PromiseOutcome::Rejected(rejection) => visit_value(&rejection.value)?,
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
MicrotaskJob::PromiseReaction { reaction, outcome } => {
|
|
173
|
-
match reaction {
|
|
174
|
-
PromiseReaction::Then {
|
|
175
|
-
on_fulfilled,
|
|
176
|
-
on_rejected,
|
|
177
|
-
..
|
|
178
|
-
} => {
|
|
179
|
-
if let Some(handler) = on_fulfilled {
|
|
180
|
-
visit_value(handler)?;
|
|
181
|
-
}
|
|
182
|
-
if let Some(handler) = on_rejected {
|
|
183
|
-
visit_value(handler)?;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
PromiseReaction::Finally { callback, .. } => {
|
|
187
|
-
if let Some(callback) = callback {
|
|
188
|
-
visit_value(callback)?;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
PromiseReaction::FinallyPassThrough {
|
|
192
|
-
original_outcome, ..
|
|
193
|
-
} => match original_outcome {
|
|
194
|
-
PromiseOutcome::Fulfilled(value) => visit_value(value)?,
|
|
195
|
-
PromiseOutcome::Rejected(rejection) => visit_value(&rejection.value)?,
|
|
196
|
-
},
|
|
197
|
-
PromiseReaction::Combinator { .. } => {}
|
|
198
|
-
}
|
|
199
|
-
match outcome {
|
|
200
|
-
PromiseOutcome::Fulfilled(value) => visit_value(value)?,
|
|
201
|
-
PromiseOutcome::Rejected(rejection) => visit_value(&rejection.value)?,
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
Ok(())
|
|
206
|
-
}
|