Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/dev/docs/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export function walk(obj, fn, k = null) {

export function getUsedLinks(obj, links, usedLinks = {}) {
walk(obj, (t, k, recurse) => {
if (t && t.type === 'link') {
// don't follow the link if it's already in links, that's circular
if (t && t.type === 'link' && !usedLinks[t.id]) {
usedLinks[t.id] = links[t.id];
getUsedLinks(links[t.id], links, usedLinks);
}
Expand Down
17 changes: 14 additions & 3 deletions packages/dev/parcel-packager-docs/DocsPackager.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ module.exports = new Packager({

function walkLinks(obj) {
walk(obj, (t, k, recurse) => {
if (t && t.type === 'link') {
// don't follow the link if it's already in links, that's circular
if (t && t.type === 'link' && !links[t.id]) {
links[t.id] = nodes[t.id];
walkLinks(nodes[t.id]);
}
Expand All @@ -186,13 +187,21 @@ async function parse(asset) {
let buffer = await asset.getBuffer();
return [asset.id, v8.deserialize(buffer)];
}

// cache things in pre-visit order so the references exist
function walk(obj, fn) {
// cache so we don't recompute
let cache = new Map();
// circular is to make sure we don't traverse over an object we visited earlier in the recursion
let circular = new Set();

let visit = (obj, fn, k = null) => {
let recurse = (obj) => {
if (circular.has(obj)) {
return {
type: 'link',
id: obj.id
};
}
if (cache.has(obj)) {
return cache.get(obj);
}
Expand All @@ -202,14 +211,16 @@ function walk(obj, fn) {
obj.forEach((item, i) => resultArray[i] = visit(item, fn, k));
return resultArray;
} else if (obj && typeof obj === 'object') {
circular.add(obj);
let res = {};
cache.set(obj, res);
for (let key in obj) {
res[key] = visit(obj[key], fn, key);
}
circular.delete(obj);
return res;
} else {
cache.set(obj, obj);
// don't cache things like null/undefined
return obj;
}
};
Expand Down