Thinking about the behavior of JSON.stringify(), I remembered that it throws an error when encountering circular object references. I realized that I haven't specifically handled that in NBTify, so you simply get to a Maximum call stack exceeded error when writing a circular object structure to NBT. This isn't ideal, and I should detect this before the user runs into it, just like JSON.stringify() does.
Found an example of how to detect them on MDN, this one can be used as a JSON replacer callback, and it will remove any circular object references before serializing to JSON. While this essentially makes the circular object "fully" serializable, I will go with throwing an error instead, like JSON.stringify() does, since I want it to be something that should be handled specifically by the user, where they can choose what to do with the circular references, rather than implicitly removing them inside of NBTify.
const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
};
JSON.stringify(circularReference, getCircularReplacer());
// {"otherData":123}
Because of that, it also further sways me to throw an error for inconsistent ListTag item types, rather than silently excluding them from the written NBT buffer (#21).
I think I will silently remove unsupported JavaScript types during the writing process though, like for null, undefined, Symbol, and function values (#20). That's what JSON.stringify() does for any function values on objects, and I think it keeps things straightforward to be able to simply pass most objects right into NBTify, but also still be explicit in throwing knowledgeable errors for object structure issues, like circular object references and array item type inconsistencies.
Thinking about the behavior of
JSON.stringify()
, I remembered that it throws an error when encountering circular object references. I realized that I haven't specifically handled that in NBTify, so you simply get to aMaximum call stack exceeded
error when writing a circular object structure to NBT. This isn't ideal, and I should detect this before the user runs into it, just likeJSON.stringify()
does.Detecting and fixing circular references in JavaScript - Stack Overflow TypeError: cyclic object value - MDN
Found an example of how to detect them on MDN, this one can be used as a JSON replacer callback, and it will remove any circular object references before serializing to JSON. While this essentially makes the circular object "fully" serializable, I will go with throwing an error instead, like
JSON.stringify()
does, since I want it to be something that should be handled specifically by the user, where they can choose what to do with the circular references, rather than implicitly removing them inside of NBTify.Because of that, it also further sways me to throw an error for inconsistent
ListTag
item types, rather than silently excluding them from the written NBT buffer (#21).I think I will silently remove unsupported JavaScript types during the writing process though, like for
null
,undefined
,Symbol
, andfunction
values (#20). That's whatJSON.stringify()
does for anyfunction
values on objects, and I think it keeps things straightforward to be able to simply pass most objects right into NBTify, but also still be explicit in throwing knowledgeable errors for object structure issues, like circular object references and array item type inconsistencies.