spine.ts 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. /**
  2. * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { State } from '../state';
  7. import { StateTransform } from '../transform';
  8. import { StateObject, StateObjectCell } from '../object';
  9. export { StateTreeSpine }
  10. /** The tree spine allows access to ancestor of a node during reconciliation. */
  11. interface StateTreeSpine {
  12. getAncestorOfType<T extends StateObject.Ctor>(type: T): StateObject.From<T> | undefined;
  13. getRootOfType<T extends StateObject.Ctor>(type: T): StateObject.From<T> | undefined;
  14. }
  15. namespace StateTreeSpine {
  16. export class Impl implements StateTreeSpine {
  17. private current: StateObjectCell | undefined = void 0;
  18. setSurrent(cell?: StateObjectCell) {
  19. this.current = cell;
  20. }
  21. getAncestorOfType<T extends StateObject.Ctor>(t: T): StateObject.From<T> | undefined {
  22. if (!this.current) return void 0;
  23. let cell = this.current;
  24. while (true) {
  25. cell = this.cells.get(cell.transform.parent)!;
  26. if (!cell.obj) return void 0;
  27. if (cell.obj.type === t.type) return cell.obj as StateObject.From<T>;
  28. if (cell.transform.ref === StateTransform.RootRef) return void 0;
  29. }
  30. }
  31. getRootOfType<T extends StateObject.Ctor>(t: T): StateObject.From<T> | undefined {
  32. if (!this.current) return void 0;
  33. let cell = this.current;
  34. let ret: StateObjectCell | undefined = void 0;
  35. while (true) {
  36. cell = this.cells.get(cell.transform.parent)!;
  37. if (!cell.obj) return void 0;
  38. if (cell.obj.type === t.type) {
  39. ret = cell;
  40. }
  41. if (cell.transform.ref === StateTransform.RootRef) return ret ? ret.obj as StateObject.From<T> : void 0;
  42. }
  43. }
  44. constructor(private cells: State.Cells) {
  45. }
  46. }
  47. }