* Helper function that navigates from a starting point node (the `from` node) * using provided set of navigation instructions (within `path` argument).
(from: Node, instructions: (number | NodeNavigationStep)[])
| 222 | * using provided set of navigation instructions (within `path` argument). |
| 223 | */ |
| 224 | function navigateToNode(from: Node, instructions: (number | NodeNavigationStep)[]): RNode { |
| 225 | let node = from; |
| 226 | for (let i = 0; i < instructions.length; i += 2) { |
| 227 | const step = instructions[i]; |
| 228 | const repeat = instructions[i + 1] as number; |
| 229 | for (let r = 0; r < repeat; r++) { |
| 230 | if (ngDevMode && !node) { |
| 231 | throw nodeNotFoundAtPathError(from, stringifyNavigationInstructions(instructions)); |
| 232 | } |
| 233 | // `nodeNotFoundAtPathError` above would normally catch a missing node too, but it's |
| 234 | // dev-mode only. Guard against it here so production throws a coded RuntimeError instead |
| 235 | // of a raw TypeError when dereferencing `node` below. |
| 236 | if (!node) { |
| 237 | throw new RuntimeError( |
| 238 | RuntimeErrorCode.HYDRATION_MISSING_NODE_ON_PATH, |
| 239 | ngDevMode && |
| 240 | 'During hydration Angular was unable to locate a node using a recorded navigation path. This usually means the client-rendered DOM no longer matches the server-rendered HTML.', |
| 241 | ); |
| 242 | } |
| 243 | switch (step) { |
| 244 | case NODE_NAVIGATION_STEP_FIRST_CHILD: |
| 245 | node = node.firstChild!; |
| 246 | break; |
| 247 | case NODE_NAVIGATION_STEP_NEXT_SIBLING: |
| 248 | node = node.nextSibling!; |
| 249 | break; |
| 250 | } |
| 251 | } |
| 252 | } |
| 253 | if (ngDevMode && !node) { |
| 254 | throw nodeNotFoundAtPathError(from, stringifyNavigationInstructions(instructions)); |
| 255 | } |
| 256 | // Same as above: `node` can legitimately end up null here (the path's last step ran off |
| 257 | // the end of the real DOM) without the loop ever dereferencing it further, so the raw |
| 258 | // TypeError guard above never gets a chance to fire for this case. Catch it here instead, |
| 259 | // since this function's return type promises a non-null `RNode`. |
| 260 | if (!node) { |
| 261 | throw new RuntimeError( |
| 262 | RuntimeErrorCode.HYDRATION_MISSING_NODE_ON_PATH, |
| 263 | ngDevMode && |
| 264 | 'During hydration Angular was unable to locate a node using a recorded navigation path. This usually means the client-rendered DOM no longer matches the server-rendered HTML.', |
| 265 | ); |
| 266 | } |
| 267 | return node as RNode; |
| 268 | } |
| 269 | |
| 270 | /** |
| 271 | * Locates an RNode given a set of navigation instructions (which also contains |
no test coverage detected