Skip to content
This repository was archived by the owner on Feb 22, 2018. It is now read-only.

[WIP] feat(ChangeDetector): unified architecture #1348

Closed
wants to merge 5 commits into from

Conversation

vicb
Copy link
Contributor

@vicb vicb commented Aug 13, 2014

This PR is a WIP and will be subject to changes

Status:

The PR should be closed to feature parity with the former implementation.
What I'll do next is to:

  • reorganize the tests (split it across different files),
  • add more tests for new features (TODO in the code),
  • replace the old impl

To do:

To discuss:

  • Should prototypes have their own group and subsequent watches be added into their own group (probably better to keep 1 set)
  • Should we allow coalescence for subsequently added watches (prototype only) -> was slower with the previous impl

@vicb
Copy link
Contributor Author

vicb commented Aug 25, 2014

Notes

There is a breaking change in this PR. When a Map or List watch is added, the changes are reported as addition rather than current value (see #774) for more details.

This makes the implementation more efficient has we don't have to possibly _revertToPreviousState. IMO this is also more correct and will enable simplifying some code - before the code path was different whether we were handling the first change or subsequent changes.

In the process the behavior seems better now (see the last assert):
Old behavior

        it('should support switching refs - gh 1158', async(() {
          var list = [0];

          var record = detector.watch(list, null, null);
          if (detector.collectChanges().moveNext()) {
            detector.collectChanges();
          }

          record.object = [1, 0];
          var iterator = detector.collectChanges()..moveNext();
          expect(...); 

          record.object = [2, 1, 0];
          iterator = detector.collectChanges()..moveNext();
          expect(iterator.current.currentValue, toEqualCollectionRecord(
              collection: ['2[null -> 0]', '1[null -> 1]', '0[0 -> 2]'],
              previous: ['0[0 -> 2]'],
              additions: ['2[null -> 0]', '1[null -> 1]'],
              moves: ['0[0 -> 2]'],
              removals: []));
        }));

New behavior:

        it('should support switching refs - gh 1158', async(() {
          var value;
          context['list'] = [0];
          var group = detector.createWatchGroup(context);
          group.watch(parse('list', collection: true), (v, _) => value = v);
          group.processChanges();

          context['list'] = [1, 0];
          group.processChanges();
          expect(...);

          context['list'] = [2, 1, 0];
          group.processChanges();
          expect(value, toEqualCollectionRecord(
              collection: ['2[null -> 0]', '1[0 -> 1]', '0[1 -> 2]'],
              previous: ['1[0 -> 1]', '0[1 -> 2]'],
              additions: ['2[null -> 0]'],
              moves: ['1[0 -> 1]', '0[1 -> 2]']));
        }));

ChangeDetector(this._fieldGetterFactory);

/// Creates a root watch group
WatchGroup createWatchGroup(Object context) => new WatchGroup(null, context, _fieldGetterFactory);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to talk about this more in depth. But my latest thinking is that we can not create WatchGroup with context. The context needs to be something which we can assign later. The reason for this is that we want to be able to reset the context at runtime. The benefit would be to be able to reuse an instance of WatchGroup for performance reasons. Let's discus.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting the context later should be implemented with the ProtoWatchGroup / ProtoRecord

@vicb
Copy link
Contributor Author

vicb commented Sep 11, 2014

@mhevery Could you please check the latest commit ("fixup: do not detach if not attached"). It is here to fix an issue with this test where the ng-if contains a content directive. The directive is both AttachAware and DetachAware but when the if branch is not taken, the scope is destroyed and the directive never got attached. However it got detached when the scope is detroyed.

All tests now pass with the new architecture, it would be great to test g3 code with this to see if everything works as expected.

@mhevery
Copy link
Contributor

mhevery commented Oct 2, 2014

Closing In favor for v2

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

Successfully merging this pull request may close these issues.

4 participants