* Resolves a target path relative to this context. * @param target The path to resolve * @returns The field corresponding to the target path.
(target: SchemaPath<U, SchemaPathRules>)
| 65 | * @returns The field corresponding to the target path. |
| 66 | */ |
| 67 | private resolve<U>(target: SchemaPath<U, SchemaPathRules>): ReadonlyFieldTree<U> { |
| 68 | if (!this.cache.has(target)) { |
| 69 | const resolver = computed<ReadonlyFieldTree<unknown>>(() => { |
| 70 | const targetPathNode = FieldPathNode.unwrapFieldPath(target); |
| 71 | |
| 72 | // First, find the field where the root our target path was merged in. |
| 73 | // We determine this by walking up the field tree from the current field and looking for |
| 74 | // the place where the LogicNodeBuilder from the target path's root was merged in. |
| 75 | // We always make sure to walk up at least as far as the depth of the path we were bound to. |
| 76 | // This ensures that we do not accidentally match on the wrong application of a recursively |
| 77 | // applied schema. |
| 78 | let field: FieldNode | undefined = this.node; |
| 79 | let stepsRemaining = getBoundPathDepth(); |
| 80 | while (stepsRemaining > 0 || !field.structure.logic.hasLogic(targetPathNode.root.builder)) { |
| 81 | stepsRemaining--; |
| 82 | field = field.structure.parent; |
| 83 | if (field === undefined) { |
| 84 | throw new RuntimeError( |
| 85 | RuntimeErrorCode.PATH_NOT_IN_FIELD_TREE, |
| 86 | ngDevMode && 'Path is not part of this field tree.', |
| 87 | ); |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | // Now, we can navigate to the target field using the relative path in the target path node |
| 92 | // to traverse down from the field we just found. |
| 93 | for (let key of targetPathNode.keys) { |
| 94 | field = field.structure.getChild(key); |
| 95 | if (field === undefined) { |
| 96 | throw new RuntimeError( |
| 97 | RuntimeErrorCode.PATH_RESOLUTION_FAILED, |
| 98 | ngDevMode && |
| 99 | `Cannot resolve path .${targetPathNode.keys.join('.')} relative to field ${[ |
| 100 | '<root>', |
| 101 | ...this.node.structure.pathKeys(), |
| 102 | ].join('.')}.`, |
| 103 | ); |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | return field.fieldTree; |
| 108 | }); |
| 109 | |
| 110 | this.cache.set(target, resolver); |
| 111 | } |
| 112 | return this.cache.get(target)!() as ReadonlyFieldTree<U>; |
| 113 | } |
| 114 | |
| 115 | get fieldTree(): ReadonlyFieldTree<unknown> { |
| 116 | return this.node.fieldProxy; |
no test coverage detected