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

NgRepeat compiled to JS throws NullError #1097

Closed
ufoscout opened this issue Jun 3, 2014 · 15 comments
Closed

NgRepeat compiled to JS throws NullError #1097

ufoscout opened this issue Jun 3, 2014 · 15 comments

Comments

@ufoscout
Copy link

ufoscout commented Jun 3, 2014

We are preparing a Sortable component for the next version of the Angular UI library (https://pub.dartlang.org/packages/angular_ui).
It works fine in Dartium, but when compiled to JS, the NgRepeat directive often throws a NullError.
Here the error stack in Chrome:

TypeError: Cannot read property 'set$_childHead' of null
    at Scope.destroy$0 (http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:11797:26)
    at NgRepeat__onChange_closure2.call$1 (http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:15937:23)
    at _CollectionChangeRecord.forEachRemoval$1 (http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:53360:11)
    at NgRepeat._onChange$1 (http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:15802:17)
    at NgRepeat_expression_closure0.call$2 (http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:15886:19)
    at Watch.reactionFn$2 (http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:24887:30)
    at Watch.invoke$0 (http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:24897:12)
    at RootWatchGroup.detectChanges$5$changeLog$evalStopwatch$exceptionHandler$fieldStopwatch$processStopwatch (http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:24835:26)
    at RootScope.digest$0 (http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:12110:34)
    at RootScope.<anonymous> (http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:11750:12)
    at RootScope.Scope.apply$2 [as apply$0] (http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:11756:19)
    at eval [as call$0] (eval at <anonymous> (http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:3172:14), <anonymous>:2:37) 

And here the staketrace in FF (similar but not the same):

NullError: this._parentScope is null

STACKTRACE:
.Scope.destroy$0<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:11797
.NgRepeat__onChange_closure2.call$1<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:15937
._CollectionChangeRecord.forEachRemoval$1@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:53360
.NgRepeat._onChange$1<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:15802
.NgRepeat_expression_closure0.call$2<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:15886
.Watch.reactionFn$2@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:24887
.Watch.invoke$0@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:24897
.RootWatchGroup.detectChanges$5$changeLog$evalStopwatch$exceptionHandler$fieldStopwatch$processStopwatch@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:24835
.RootScope.digest$0<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:12110
.Scope.apply$2<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:11750
.Scope.apply$2<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:11756
anonymous/<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:3172
._rootRun<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:28762
._ZoneDelegate.run$2@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:31478
.VmTurnZone._finishTurn$2<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:12917
.VmTurnZone._onRunBase$4<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:12883
.VmTurnZone._onRunUnary$5<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:12890
anonymous/<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:3184
._ZoneDelegate.runUnary$3@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:31485
._CustomizedZone.runUnary$2@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:31668
._BaseZone.runUnaryGuarded$2@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:31568
._BaseZone_bindUnaryCallback_closure.call$1<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:31626
.invokeClosure_closure0.call$0@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:4358
._IsolateContext.eval$1<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:1833
._callInIsolate@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:1466
.invokeClosure<@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:3017
.convertDartClosureToJS/$function@http://127.0.0.1:3030/angular.dart.ui/build/web/main.dart.js:3036

To reproduce the issue, checkout the dragdrop branch (https://github.com/akserg/angular.dart.ui/tree/dragdrop) and compile it to JS (pub build). Open the build result in a browser, drag of an element of a sortable list performing fast movements with the mouse. The exception is thrown multiple times and the content of the list is corrupted.
As stated before, everything works perfectly with Dart code in Dartium.

@vicb
Copy link
Contributor

vicb commented Jun 3, 2014

@ufoscout could you please try to apply the commits from #1018 and let us know if the situation improves after having merged the first and both the commits ?

@ufoscout
Copy link
Author

ufoscout commented Jun 3, 2014

@vicb I don't know exactly how to apply the commits you mentioned; however, I performed a checkout of angular.dart master, I copied the raw version of the NgRepeat from #1018 (I added a print to the constructor to be sure it was used) and then I modified my library to use angular from local path.
As before, it works with Dart/Dartium but it throws an error with JS/Firefox/Chrome.

@vicb
Copy link
Contributor

vicb commented Jun 3, 2014

git apply could have helped here but what you've done is perfectly fine.

Some other things you can do to investigate:

  • try to use angular from the master branch (by using a path pkg) - you'll probably need to adapt some code, check the examples and ask if something is not clear,
  • try to come with the minimal example that triggers the error, there is a lot of code in the linked repo.

Thanks

@ufoscout
Copy link
Author

ufoscout commented Jun 3, 2014

@vicb I performed different attempts but no luck at all.
I have been able to create a small project that reproduces the issue, it can be checked out here:
https://github.com/ufoscout/NgRepeatIssue
It does not start at all in Firefox (another strange thing...); however, the error can be easily reproduced with Chrome. In this new project the error appears less often than in the original one. It seems that it is related to the speed the actions are performed. To reproduce it you have to move the mouse very (very very) fast during a drag operation.

@vicb
Copy link
Contributor

vicb commented Jun 4, 2014

Firefox does not work (as reported)
I can not trigger the issue with Chrome, what VM version do you use, could you try with Dart VM version: 1.5.0-dev.3.4

My setup:

  • Ubuntu 14.04 64b
  • Dart VM version: 1.5.0-dev.3.4 (Mon Jun 2 08:43:55 2014) on "linux_x64"
  • Chrome Version 37.0.2017.2 dev
  • Firefox 30.0

@vicb
Copy link
Contributor

vicb commented Jun 4, 2014

Seems like I can trigger the error finally, I'll take a deeper look

@vicb
Copy link
Contributor

vicb commented Jun 4, 2014

For now it seems like a bug in the change detection, see what happens when dragging an item to the bottom of the list:

drag node [7] over node [6] js_primitives.dart:25
++  _onCollectionChange js_primitives.dart:25
moveFn 7 -> 6 js_primitives.dart:25
moveFn 6 -> 7 js_primitives.dart:25
moveFn 8 -> 8 js_primitives.dart:25
moveFn 9 -> 9 js_primitives.dart:25
drag node [8] over node [7] js_primitives.dart:25
++  _onCollectionChange js_primitives.dart:25
moveFn 8 -> 7 js_primitives.dart:25
moveFn 7 -> 8 js_primitives.dart:25
moveFn 9 -> 9 js_primitives.dart:25
drag node [9] over node [8] js_primitives.dart:25
++  _onCollectionChange js_primitives.dart:25
remove at index 9 js_primitives.dart:25
destroying scope :0:0:9 js_primitives.dart:25
moveFn 9 -> 8 js_primitives.dart:25
moveFn 8 -> 9 

We should not remove / destroy at index 9 - we should only swap the two last els (8 & 9)

I have now to check if this is also applicable to the Dart version... and fix it :)

@vicb
Copy link
Contributor

vicb commented Jun 4, 2014

The Dart version is fine

++  _onCollectionChange
moveFn 7 -> 6
moveFn 6 -> 7
moveFn 8 -> 8
moveFn 9 -> 9
drag node [8] over node [7]
++  _onCollectionChange
moveFn 8 -> 7
moveFn 7 -> 8
moveFn 9 -> 9
drag node [9] over node [8]
++  _onCollectionChange
moveFn 9 -> 8
moveFn 8 -> 9

@vicb
Copy link
Contributor

vicb commented Jun 4, 2014

This snippet shows the bad behavior (also in Dart)

  var detector = new DirtyCheckingChangeDetector(null);

  var iterator;

  var list = ['a', 'b', 'c'];
  detector.watch(list, null, null);
  iterator = detector.collectChanges()..moveNext();
  print(iterator.current.currentValue);

  list..clear()..addAll(['b', 'a', 'c']);
  iterator = detector.collectChanges()..moveNext();
  print(iterator.current.currentValue);

  list..clear()..addAll(['b', 'c', 'a']);
  iterator = detector.collectChanges()..moveNext();
  print(iterator.current.currentValue);

I don't know why but this seems to work in a unit test !
Anyway I'm closer to resolution than ever berfore ;)

@vicb
Copy link
Contributor

vicb commented Jun 4, 2014

Ah got it: it works in checked mode, fails in non checked mode - nothing to do with JS vs Dart

@ufoscout
Copy link
Author

ufoscout commented Jun 4, 2014

@vicb wow! You're going fast 👍 Thank you. I'm looking forward to see this fixed!

@vicb
Copy link
Contributor

vicb commented Jun 4, 2014

I have a fix but I need to make sure everything is correct before merging, this code is critical

@akserg
Copy link

akserg commented Jun 4, 2014

Thanks Victor,
Very appreciated you effort. Hope to see bug fix in next release.

Sergey.

vicb added a commit to vicb/angular.dart that referenced this issue Jun 4, 2014
vicb added a commit to vicb/angular.dart that referenced this issue Jun 4, 2014
vicb added a commit to vicb/angular.dart that referenced this issue Jun 4, 2014
vicb added a commit to vicb/angular.dart that referenced this issue Jun 4, 2014
@vicb
Copy link
Contributor

vicb commented Jun 4, 2014

Well I'm quite happy to have fixed this bug that I was chasing for some time - thanks @ufoscout for having provided a repro.
I have also found an other issue while working on this, the move N -> N should not happen, this one will be for next week

@vicb vicb closed this as completed in 8dbeefc Jun 4, 2014
@ufoscout
Copy link
Author

ufoscout commented Jun 4, 2014

@vicb you fixed it in less than 24 hours! impressive! I really need to thank you.

vicb added a commit that referenced this issue Jul 9, 2014
closes #1097

Conflicts:
	lib/change_detection/dirty_checking_change_detector.dart
dsalsbury pushed a commit to dsalsbury/angular.dart that referenced this issue Jul 16, 2014
dsalsbury pushed a commit to dsalsbury/angular.dart that referenced this issue Jul 16, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

No branches or pull requests

4 participants