54 lines
1.1 KiB
JavaScript
54 lines
1.1 KiB
JavaScript
export const DELETE_PROPERTY = Symbol('DELETE_PROPERTY');
|
|
|
|
|
|
export class String_Keyed_Stack {
|
|
constructor(target={}, stack=[]) {
|
|
Object.assign(this, { target, stack });
|
|
}
|
|
|
|
push(updates={}) {
|
|
const frame = {}
|
|
this.stack.push(frame);
|
|
for (const [key, value] of Object.entries(updates)) {
|
|
|
|
if (key in this.target) {
|
|
frame[key] = this.target[key];
|
|
} else {
|
|
frame[key] = DELETE_PROPERTY;
|
|
}
|
|
|
|
if (value === DELETE_PROPERTY) {
|
|
delete this.target[key];
|
|
} else {
|
|
this.target[key] = value;
|
|
}
|
|
}
|
|
return frame;
|
|
}
|
|
|
|
push_defined(updates={}) {
|
|
this.push(Object.fromEntries(Object.entries(updates).filter(([k ,v]) => v !== undefined )));
|
|
}
|
|
|
|
pop(copy_previous_state=false) {
|
|
const frame = this.stack.pop();
|
|
const { target } = this;
|
|
|
|
const return_value = copy_previous_state ? { ...target } : null;
|
|
|
|
for (const [key, value] of Object.entries(frame)) {
|
|
if (value === DELETE_PROPERTY) {
|
|
delete target[key];
|
|
} else {
|
|
target[key] = value;
|
|
}
|
|
}
|
|
|
|
return return_value;
|
|
}
|
|
|
|
get top_reverse_delta() {
|
|
return this.stack.at(-1);
|
|
}
|
|
|
|
} |