You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
2.6 KiB
JavaScript

"use strict";
const isPlaceholder = require("../util/is-placeholder");
module.exports = function createPlaceholderManager() {
let placeholders = [];
return {
markProperty: function (object, property) {
placeholders.push({
type: "property",
object: object,
property: property
});
},
markSet: function (set) {
placeholders.push({
type: "set",
set: set
});
},
markArray: function (array) {
placeholders.push({
type: "array",
array: array
});
},
markMap: function (map) {
placeholders.push({
type: "map",
map: map
});
},
fillInPlaceholders: function (seen) {
function getSeenItem(placeholder) {
if (seen.has(placeholder._deserializationId)) {
return seen.get(placeholder._deserializationId);
} else {
throw new Error(`Did not encounter an object with the ID ${placeholder._deserializationId}`);
}
}
function fillInSetPlaceholders(set) {
let originalItems = Array.from(set.values());
set.clear();
for (let item of originalItems) {
if (isPlaceholder(item)) {
set.add(getSeenItem(item));
} else {
set.add(item);
}
}
}
function fillInArrayPlaceholders(array) {
array.forEach((item, i) => {
if (isPlaceholder(item)) {
array[i] = getSeenItem(item);
}
});
}
function fillInMapPlaceholders(map) {
let originalItems = Array.from(map.entries());
map.clear();
for (let [key, value] of originalItems) {
let newKey, newValue;
if (isPlaceholder(key)) {
newKey = getSeenItem(key);
} else {
newKey = key;
}
if (isPlaceholder(value)) {
newValue = getSeenItem(value);
} else {
newValue = value;
}
map.set(newKey, newValue);
}
}
function fillInPlaceholderProperty(object, property) {
object[property] = getSeenItem(object[property]);
}
placeholders.forEach((marker) => {
/* NOTE: The Set/Map implementations below are probably slow. Maybe there's a faster implementation? */
if (marker.type === "set") {
fillInSetPlaceholders(marker.set);
} else if (marker.type === "array") {
fillInArrayPlaceholders(marker.array);
} else if (marker.type === "map") {
fillInMapPlaceholders(marker.map);
} else if (marker.type === "property") {
fillInPlaceholderProperty(marker.object, marker.property);
} else {
throw new Error(`Unrecognized placeholder marker type: ${marker.type}`);
}
});
/* To ensure that any accidental future invocations of this function will fail loudly. */
placeholders = null;
}
};
};