Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Cannot set property 'pur' of undefined #16164

Closed
1 of 3 tasks
Thrilleratplay opened this issue Aug 10, 2017 · 10 comments
Closed
1 of 3 tasks

Cannot set property 'pur' of undefined #16164

Thrilleratplay opened this issue Aug 10, 2017 · 10 comments

Comments

@Thrilleratplay
Copy link

I'm submitting a ...

  • bug report
  • feature request
  • other (Please do not submit support requests here (see above))

Current behavior:
After upgrading to v1.6.5, a panel whose visibility delayed using $timeout is throwing an error angular.js:14642 TypeError: Cannot set property 'pur' of undefined

Expected / new behavior:
Timeout cancelation should fail gracefully

Minimal reproduction of the problem with instructions:
Unfortunately I have not been able to create a Plunker that recreates this issue. In the environment I am working in, I am able to regularly reproduce this error by moving the mouse in and out of the element that triggers the showPanel/hidePanel functions three or four times.

Below I have attached a stacktrace and relative code. Please let me know if this is insufficient and I will continue to try to recreate the issue in Plunker.

Angular version: 1.6.5 but not version 1.6.4

Browser: Chrome 60 (only browser tested)

Anything else:

I am assuming that it is related to this commit: fix($timeout/$interval): do not trigger a digest on cancel and the simplest fix would be to add a check here:

function markQStateExceptionHandled(state) {
  if (state) {
    state.pur = true;
  }
}

** Debugging information**

Stacktrace:

angular.js:14642 TypeError: Cannot set property 'pur' of undefined
    at markQStateExceptionHandled (angular.js:17320)
    at markQExceptionHandled (angular.js:17323)
    at Function.timeout.cancel (angular.js:20422)
    at e.i.hidePanel (scope.component.js:188)
    at fn (eval at compile (angular.js:15500), <anonymous>:4:186)
    at callback (angular.js:27285)
    at Scope.$eval (angular.js:18372)
    at Scope.$apply (angular.js:18472)
    at HTMLDivElement.<anonymous> (angular.js:27290)
    at specialMouseHandlerWrapper (angular.js:3782)
    at HTMLDivElement.eventHandler (angular.js:3759)
(anonymous) @ angular.js:14642
(anonymous) @ angular.js:11102
$apply @ angular.js:18477
(anonymous) @ angular.js:27290
specialMouseHandlerWrapper @ angular.js:3782
eventHandler @ angular.js:3759

Relative element with mouse event triggers

<div class="flex flex-auto relative"
     ng-mouseenter="scopeCtrl.showPanel()"
     ng-mouseleave="scopeCtrl.hidePanel()"
     ng-class="(scopeCtrl.collapsed ? 'closed' : 'open'">
  <!-- Additional content here-->
</div>

Relative JavaScript functions

var vm = this;
var panelTimer;

/**
 * Delayed show Scope panel
 */
vm.showPanel = function() {
  $timeout.cancel(panelTimer);
  panelTimer = $timeout(function() {
    vm.collapsed = false;
  }, 300);
};

/**
 * Delayed delayed Scope panel
 */
vm.hidePanel = function() {
  $timeout.cancel(panelTimer);
  panelTimer = $timeout(function() {
    vm.collapsed = true;
  }, 300);
};
@gkalpak
Copy link
Member

gkalpak commented Aug 10, 2017

This is very strange. All promises have a $$state property from the get go. I can't imagine how it is would be possible to end up at that point of the code with $$state being undefined 😕

A repro woud definitely help.

(Other than the missing repro, awesome bug report  ❤️ )

@Thrilleratplay
Copy link
Author

My apologies, this is an issue of my own creation and explains why I couldn't reproduce the issue on Plunker. I was using Bluebird.js with angular-bluebird-promises to override the built in Angular promise service for the cancelable promise feature. I guess these have both diverged enough from Kris Kowal's Q.

@gkalpak
Copy link
Member

gkalpak commented Aug 11, 2017

Hm....so I guess we have made it impossible (or possibly just harder than necessary) for people to swap $q with a different implementation 😕
If it is easy to fix and someone wants to take a look at what it would take to make it more straightforward, please go ahead.

@rickyk586
Copy link

rickyk586 commented Oct 11, 2017

Instead of using $mdToast.showSimple('Toast Message'), use:

$mdToast.show({
	template: '<md-toast><div class="md-toast-content">Toast Message</div></md-toast>',
	hideDelay: false
});
$timeout(() => $mdToast.hide(), 2900);

vbraun added a commit to vbraun/angular.js that referenced this issue Feb 26, 2018
For testing, it can be useful to run with other promise
implementations like Bluebird.js + angular-bluebird-promises. This
broke in angularjs 1.6 with a "TypeError: Cannot set property 'pur' of
undefined".

Closes angular#16164
@petebacondarwin
Copy link
Contributor

I'm going to land this with comments explaining why those if statements are there.

@petebacondarwin petebacondarwin self-assigned this Feb 26, 2018
@petebacondarwin petebacondarwin modified the milestones: Backlog, 1.6.x, 1.6.10 Feb 26, 2018
@wiltzius
Copy link

May I propose re-opening this issue? The PR referenced above #16471 landing would be very helpful -- we're currently stuck on 1.6.4 because we're relying on bluebird to install our own generic promise rejection handler. Much appreciated, thank you.

@gkalpak
Copy link
Member

gkalpak commented May 27, 2018

Hm...I think we were supposed to land #16471 (but didn't) 😕
Let's move the discussion there.

@wiltzius, do you by any chance know (or have a way to find out) the answer to https://github.com/angular/angular.js/pull/16471/files#r172260779?
(Or share a minimal reproduction, so I can investigate myself.)

@wiltzius
Copy link

Yes, here's a minimal repo:

https://github.com/wiltzius/angularjs-webpack

I just cloned a basic starter repo (https://github.com/preboot/angularjs-webpack) and then made the following changes to it:

wiltzius/angularjs-webpack@4b8342f

Hopefully that commit ^ should tell you all you need to know.

Obviously its contrived, but I basically copied the $interval code from ng-infinite-scroll (which is a project we're using that's causing this problem). See that code here:

https://github.com/sroze/ngInfiniteScroll/blob/master/src/infinite-scroll.js#L257

Appreciate you taking a look at this!

@wiltzius
Copy link

btw this is tagged 1.6.10 but 1.7.0 (all versions >= 1.6.5) exhibit the same behavior.

@gkalpak
Copy link
Member

gkalpak commented May 28, 2018

Thx! So, afaict (based on your repro) is that the answer to https://github.com/angular/angular.js/pull/16471/files#r172260779 is that isStateExceptionHandled() is indeed not called when not using the built-in $q.

@wiltzius, would you like to take over #16471, remove the unnecessary change to isStateExceptionHandled() and add a comment in markQStateExceptionHandled mentioning why it is needed?

gkalpak pushed a commit that referenced this issue Nov 15, 2018
For testing, it can be useful to overwrite `$q` with other promise
implementions, such as Bluebird + angular-bluebird-promises. This broke
in v1.6.x with "TypeError: Cannot set property 'pur' of undefined".

Closes #16164

Closes #16471
gkalpak pushed a commit that referenced this issue Nov 15, 2018
For testing, it can be useful to overwrite `$q` with other promise
implementions, such as Bluebird + angular-bluebird-promises. This broke
in v1.6.x with "TypeError: Cannot set property 'pur' of undefined".

Closes #16164

Closes #16471
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants