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
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;
|
|
}
|
|
};
|
|
};
|