Files
nodejs.esm-library/experiments/os1.mjs
2026-04-04 07:08:37 +02:00

121 lines
2.7 KiB
JavaScript

// Note: Only handled objects and primitives are allowed to be set/pushed/mapped
import { inspect } from 'node:util';
class Not_Storable_Error extends Error {
constructor({ storage, value, prop, id }) {
const type = value === null ? 'null' : typeof value;
const location = prop ? `property "${prop}" of record #${id}` : `record #${id}`;
super(`Cannot store value of type "${type}" in ${location}: ${inspect(value)}`);
this.name = 'Not_Storable_Error';
this.storage = storage;
this.value = value;
}
}
class Not_Mutable_Error extends Error {
constructor({ storage, value, prop, id }) {
const type = value === null ? 'null' : typeof value;
const location = prop ? `property "${prop}" of record #${id}` : `record #${id}`;
super(`Cannot set ${location}: record is immutable (tried to store value of type "${type}": ${inspect(value)})`);
this.name = 'Not_Mutable_Error';
this.storage = storage;
this.value = value;
}
}
function load_descriptor({ type, value }, { storage, mutable }) {
if (type === 'primitive') {
return value;
} else {
throw new Error('not implemented');
}
}
const Record_Handler = {
get(target, prop, receiver) {
const { storage, id, mutable } = target;
const result_descriptor = storage.get_record_property(id, prop);
if (result_descriptor) {
return load_descriptor(result_descriptor, { storage, mutable });
} else {
return undefined;
}
},
set(target, prop, value) {
const { storage, id, mutable } = target;
if (!mutable) {
throw new Not_Mutable_Error({ storage, id, prop, value });
}
if (!storage.can_be_stored(value)) {
throw new Not_Storable_Error({ storage, id, prop, value });
}
storage.set_record_property(id, prop, value);
return true;
}
};
class Storage {
#pending_id = 1;
#records = new Map();
create_record(data=undefined, mutable=true) {
const id = this.acquire_new_id();
const property_bag = {};
const result = new Proxy({
storage: this,
id,
property_bag,
mutable,
}, Record_Handler);
this.#records.set(id, property_bag);
if (data !== undefined) {
Object.assign(result, data);
}
return result;
}
get_record_property(item_id, property) {
console.log("Should get record property", { item_id, property });
return { type: 'primitive', value: 'Hello' };
}
set_record_property(item_id, property, value) {
console.log("Should set record property", { item_id, property, value });
}
can_be_stored(value) {
if (typeof value === 'string') {
return true;
} else {
return false;
}
}
acquire_new_id() {
return this.#pending_id++;
}
};
const s1 = new Storage();
const p1 = s1.create_record({stuff: 'hello'}, true);
console.log(p1.blargh);
//p1.stuff = ['hello', 'world'];