angular: checkBindingNoChanges() attempting to check an index that does not exist

I’m submitting a…


[X] Bug report  

Minimal reproduction of the problem with instructions

@lishichao1002 was kind enough to provide a repro case at http://plnkr.co/edit/FcuEqLLp8UeS5JXinsGi?p=preview which is similar to what I’m seeing (the error seems limited to cases where visibility of a component is toggled).

To see the error:

  1. Open the above Plunker
  2. Open the Chrome console
  3. Press “Open OK” to see that the overlay appears when it is opened with a direct function call
  4. Press “Open Appear Error” to see the Cannot read property 'name' of undefined error in checkBindingNoChanges() when a binding is used to display the overlay.

Environment


Angular version: 5.2.2


Browser:
- [X] Chrome (desktop) version 64.0.3282.119
 

There seems to be a bug or unhandled error problem related to checkBindingNoChanges() in /core/src/view/util.ts.

The function looks like this:

export function checkBindingNoChanges(view, def, bindingIdx, value) {
    var /** @type {?} */ oldValue = view.oldValues[def.bindingIndex + bindingIdx];
    if ((view.state & 1 /* BeforeFirstCheck */) || !devModeEqual(oldValue, value)) {
        var /** @type {?} */ bindingName = def.bindings[def.bindingIndex].name;
        throw expressionChangedAfterItHasBeenCheckedError(Services.createDebugContext(view, def.nodeIndex), bindingName + ": " + oldValue, bindingName + ": " + value, (view.state & 1 /* BeforeFirstCheck */) !== 0);
    }
}

During unit testing, I’m intermittently getting an error from checkBindingNoChanges(): Cannot read property 'name' of undefined at checkBindingNoChanges

I was able to trigger this while “break on exceptions” was on, and took the following screenshot. checkBindingNoChanges() tries to look up the binding name via def.bindings[def.bindingIndex].name. But since def.bindingIndex is currently 20, this evaluates to def.bindings[20].name. But def.bindings only has 10 elements in it, which results in the error I’m seeing.

Unfortunately, I have no real way to try and build a repro case for this, since I have no idea how Angular is getting into this state. But something seems to be getting out of sync somewhere, possibly the compiler? Should there at least be a check to make sure the index that is being checked exists?

image

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 12
  • Comments: 19 (5 by maintainers)

Commits related to this issue

Most upvoted comments

Facing the same problem too. By the way, i use ChangeDetectorRef as a workaround to fix this

image Using http://plnkr.co/edit/FcuEqLLp8UeS5JXinsGi?p=preview provided by @lishichao1002

I also met this problem。

GwImgPreviewComponent.html:9 ERROR TypeError: Cannot read property 'name' of undefined
    at checkBindingNoChanges (util.js:126)
    at checkNoChangesNodeInline (view.js:557)
    at checkNoChangesNode (view.js:530)
    at debugCheckNoChangesNode (services.js:563)
    at debugCheckDirectivesFn (services.js:469)
    at Object.View_GwImgPreviewComponent_0._co [as updateDirectives] (GwImgPreviewComponent.html:9)
    at Object.debugUpdateDirectives [as updateDirectives] (services.js:446)
    at checkNoChangesView (view.js:367)
    at callViewAction (view.js:722)
    at execComponentViewsAction (view.js:671)

I write a plunker to display this question http://plnkr.co/edit/FcuEqLLp8UeS5JXinsGi?p=preview

Upgrading to 5.2.9 fixed this for me, I was previously on 5.2.2.

Thanks, @vicb. Looks like the change has the lookup index use bindingIdx instead of def.bindingIndex, which seems like it would make a big difference. From the debug screenshot I sent, that would change things to do def.bindings[2].name instead of def.bindings[20].name. Which is obviously critical, since the former is a valid index while the latter is not!

Is there a way to actually test this before a new version is pushed to NPM? I think there’s a way to point the dependency to Github in the package.json, but I’m not sure I’ve ever needed to do that. I’ll Google around and see if I can find the answer.

@vicb Updated to latest angular, still have the issue. Or has this not reached release yet (5.2.2)?

Message is still the same, pointing to the bindingName = def.bindings[def.bindingIndex].name;

It’s a simple element:

            <i class="toggle-icon fa cursor"
               [ngClass]="{'mat-down': allToggleOpen, 'mat-right': !allToggleOpen}"
               (click)="toggleAllCards(!allToggleOpen); $event.preventDefault()"
            ></i>

The removing the ngClass row fixes it.