refactor multiversion

This commit is contained in:
Dmitry Vasilev
2023-11-27 18:22:40 +08:00
parent 2889d9ed45
commit 32f7851081
3 changed files with 39 additions and 27 deletions

View File

@@ -19,25 +19,22 @@ function binarySearch(arr, el, compare_fn) {
export class Multiversion {
constructor(cxt, initial) {
this.cxt = cxt
this.is_expanding_calltree_node = cxt.is_expanding_calltree_node
this.expand_calltree_node_number = cxt.expand_calltree_node_number
this.latest = initial
this.versions = [{version_number: cxt.version_counter, value: initial}]
}
is_created_during_current_expand() {
return this.expand_calltree_node_number == this.cxt.expand_calltree_node_number
}
get() {
if(!this.cxt.is_expanding_calltree_node) {
return this.latest
} else {
if(this.is_expanding_calltree_node) {
// var was created during current expansion, use its latest value
if(this.is_created_during_current_expand()) {
return this.latest
} else {
if(this.latest_copy != null) {
// value was set during expand_calltree_node, use this value
return this.latest
}
// TODO on first read, set latest and latest_copy? Note that it will
// interfere with at_moment_in_time
const version_number = this.cxt.version_counter
return this.get_version(version_number)
}
@@ -61,16 +58,11 @@ export class Multiversion {
set(value) {
const version_number = ++this.cxt.version_counter
if(this.cxt.is_expanding_calltree_node) {
if(this.is_expanding_calltree_node) {
if(this.is_created_during_current_expand()) {
this.latest = value
this.set_version(version_number, value)
this.cxt.touched_multiversions.add(this)
} else {
if(this.latest_copy == null) {
this.latest_copy = {value: this.latest}
}
this.cxt.touched_multiversions.add(this)
this.latest = value
// do nothing
}
} else {
this.latest = value

View File

@@ -194,7 +194,9 @@ export const set_record_call = cxt => {
export const do_eval_expand_calltree_node = (cxt, node) => {
cxt.is_recording_deferred_calls = false
cxt.is_expanding_calltree_node = true
cxt.touched_multiversions = new Set()
cxt.expand_calltree_node_number = cxt.expand_calltree_node_number == null
? 0
: cxt.expand_calltree_node_number + 1
// Save call counter and set it to the value it had when executed 'fn' for
// the first time
@@ -227,16 +229,6 @@ export const do_eval_expand_calltree_node = (cxt, node) => {
// Restore version_counter
cxt.version_counter = version_counter
// Recover multiversions affected by expand_calltree_node
for(let m of cxt.touched_multiversions) {
if(m.is_expanding_calltree_node) {
delete m.is_expanding_calltree_node
}
if(m.latest_copy != null) {
m.latest = m.latest_copy.value
}
}
delete cxt.touched_multiversions
cxt.is_expanding_calltree_node = false
cxt.is_recording_deferred_calls = true

View File

@@ -4682,4 +4682,32 @@ const y = x()`
const moved = COMMANDS.move_cursor(expanded, code.indexOf('return x'))
assert_equal(moved.value_explorer.result.value, 2)
}),
test('let_versions deferred calls get value', () => {
const code = `
let x = 0
function noop() {
}
function set(value) {
x = value
noop()
}
set(1)
set(2)
set(3)
export const get = () => x
`
const {state: i} = test_deferred_calls_state(code)
const second_set_call = root_calltree_node(i).children[1]
assert_equal(second_set_call.has_more_children, true)
const exp = COMMANDS.calltree.click(i, second_set_call.id)
assert_equal(exp.modules[''].get(), 3)
}),
]