aboutsummaryrefslogtreecommitdiff
path: root/src/new_fields/Doc.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/new_fields/Doc.ts')
-rw-r--r--src/new_fields/Doc.ts28
1 files changed, 23 insertions, 5 deletions
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index 9256f82c2..9efb14d03 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -292,6 +292,9 @@ export namespace Doc {
export function IsPrototype(doc: Doc) {
return GetT(doc, "isPrototype", "boolean", true);
}
+ export function IsBaseProto(doc: Doc) {
+ return GetT(doc, "baseProto", "boolean", true);
+ }
export async function SetInPlace(doc: Doc, key: string, value: Field | undefined, defaultProto: boolean) {
const hasProto = doc.proto instanceof Doc;
const onDeleg = Object.getOwnPropertyNames(doc).indexOf(key) !== -1;
@@ -581,30 +584,44 @@ export namespace Doc {
return copy;
}
- export function MakeClone(doc: Doc, cloneProto: boolean = true): Doc {
+ export function MakeClone(doc: Doc, cloneMap: Map<Doc, Doc> = new Map()): Doc {
+ if (Doc.IsBaseProto(doc)) return doc;
+ if (cloneMap.get(doc)) return cloneMap.get(doc)!;
const copy = new Doc(undefined, true);
+ cloneMap.set(doc, copy);
const exclude = Cast(doc.excludeFields, listSpec("string"), []);
Object.keys(doc).forEach(key => {
if (exclude.includes(key)) return;
const cfield = ComputedField.WithoutComputed(() => FieldValue(doc[key]));
const field = ProxyField.WithoutProxy(() => doc[key]);
- if (key === "proto" && cloneProto) {
+ if (key === "proto") {
if (doc[key] instanceof Doc) {
- copy[key] = Doc.MakeClone(doc[key]!, false);
+ copy[key] = Doc.MakeClone(doc[key]!, cloneMap);
}
} else {
if (field instanceof RefField) {
copy[key] = field;
} else if (cfield instanceof ComputedField) {
copy[key] = ComputedField.MakeFunction(cfield.script.originalScript);
+ if (field instanceof ObjectField) {
+ const list = Cast(doc[key], listSpec(Doc));
+ if (list !== undefined && !(list instanceof Promise)) {
+ copy[key] = new List<Doc>(list.filter(d => d instanceof Doc).map(d => Doc.MakeClone(d as Doc, cloneMap)));
+ } else {
+ copy[key] = doc[key] instanceof Doc ?
+ key.includes("layout[") ?
+ undefined : Doc.MakeClone(doc[key] as Doc, cloneMap) : // reference documents except copy documents that are expanded teplate fields
+ ObjectField.MakeCopy(field);
+ }
+ }
} else if (field instanceof ObjectField) {
const list = Cast(doc[key], listSpec(Doc));
if (list !== undefined && !(list instanceof Promise)) {
- copy[key] = new List<Doc>(list.filter(d => d instanceof Doc).map(d => Doc.MakeCopy(d as Doc, false)));
+ copy[key] = new List<Doc>(list.filter(d => d instanceof Doc).map(d => Doc.MakeClone(d as Doc, cloneMap)));
} else {
copy[key] = doc[key] instanceof Doc ?
key.includes("layout[") ?
- Doc.MakeCopy(doc[key] as Doc, false) : doc[key] : // reference documents except copy documents that are expanded teplate fields
+ undefined : Doc.MakeClone(doc[key] as Doc, cloneMap) : // reference documents except copy documents that are expanded teplate fields
ObjectField.MakeCopy(field);
}
} else if (field instanceof Promise) {
@@ -616,6 +633,7 @@ export namespace Doc {
});
Doc.SetInPlace(copy, "title", "CLONE: " + doc.title, true);
copy.cloneOf = doc;
+ cloneMap.set(doc, copy);
return copy;
}