mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-01-09 21:48:12 -05:00
Revert variables on catch
This commit is contained in:
@@ -416,6 +416,7 @@ not the subset of ValueScript that has actually been implemented.
|
||||
- Recursion
|
||||
- Destructuring
|
||||
- Exceptions
|
||||
- Variables changed during try block are reverted on catch
|
||||
- Local imports (not yet in the playground)
|
||||
- Tree shaking (not yet in the playground)
|
||||
- Copy-on-write optimizations
|
||||
@@ -466,7 +467,6 @@ not the subset of ValueScript that has actually been implemented.
|
||||
- `{} === {} -> true`
|
||||
- JS: `-> false`
|
||||
- This is a value semantics thing - objects don't have identity
|
||||
- Restoring variables changed during `try` when an exception is thrown
|
||||
- Enforcing `const`
|
||||
- Temporal dead zones
|
||||
- Iterators
|
||||
|
||||
22
inputs/passing/exceptions/snapshot.ts
Normal file
22
inputs/passing/exceptions/snapshot.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
// test_output! [0,1]
|
||||
|
||||
export default function () {
|
||||
return [
|
||||
test(true),
|
||||
test(false),
|
||||
];
|
||||
}
|
||||
|
||||
function test(shouldThrow: boolean) {
|
||||
let x = 0;
|
||||
|
||||
try {
|
||||
x++;
|
||||
|
||||
if (shouldThrow) {
|
||||
throw new Error("boom");
|
||||
}
|
||||
} catch {}
|
||||
|
||||
return x;
|
||||
}
|
||||
@@ -652,6 +652,29 @@ impl FunctionCompiler {
|
||||
}
|
||||
|
||||
self.apply_catch_setting();
|
||||
|
||||
let mut snap_pairs = HashSet::<(Register, Register)>::new();
|
||||
|
||||
if try_.handler.is_some() {
|
||||
let snap_registers: HashSet<Register> = self.get_mutated_registers(try_.block.span);
|
||||
|
||||
for reg in snap_registers {
|
||||
let reg_name = match ® {
|
||||
Register::Named(name) => name,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
let snap_reg = self.allocate_reg_fresh(&format!("snap_{}", reg_name));
|
||||
|
||||
self.push(Instruction::Mov(
|
||||
Value::Register(reg.clone()),
|
||||
snap_reg.clone(),
|
||||
));
|
||||
|
||||
snap_pairs.insert((reg, snap_reg));
|
||||
}
|
||||
}
|
||||
|
||||
self.block_statement(&try_.block);
|
||||
self.pop_catch_setting(); // TODO: Avoid redundant set_catch to our own finally
|
||||
|
||||
@@ -663,6 +686,10 @@ impl FunctionCompiler {
|
||||
self.label(catch_label.unwrap());
|
||||
self.apply_catch_setting(); // TODO: Avoid redundant unset_catch
|
||||
|
||||
for (reg, snap_reg) in snap_pairs {
|
||||
self.push(Instruction::Mov(Value::Register(snap_reg), reg));
|
||||
}
|
||||
|
||||
if let Some(param) = &catch_clause.param {
|
||||
let mut ec = ExpressionCompiler { fnc: self };
|
||||
|
||||
@@ -1135,4 +1162,28 @@ impl FunctionCompiler {
|
||||
|
||||
return asm;
|
||||
}
|
||||
|
||||
fn get_mutated_registers(&self, span: swc_common::Span) -> HashSet<Register> {
|
||||
let start = swc_common::Span {
|
||||
lo: span.lo,
|
||||
hi: span.lo,
|
||||
ctxt: span.ctxt,
|
||||
};
|
||||
|
||||
let end = swc_common::Span {
|
||||
lo: span.hi,
|
||||
hi: span.hi,
|
||||
ctxt: span.ctxt,
|
||||
};
|
||||
|
||||
let mut mutated_registers = HashSet::<Register>::new();
|
||||
|
||||
for (_span, mutated_name_id) in self.scope_analysis.mutations.range(start..end) {
|
||||
if let Some(Value::Register(reg)) = self.lookup_by_name_id(mutated_name_id) {
|
||||
mutated_registers.insert(reg);
|
||||
}
|
||||
}
|
||||
|
||||
mutated_registers
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user