-
Notifications
You must be signed in to change notification settings - Fork 27.5k
fix($rootScope): avoid unstable reference in $broadcast event #7445
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1572,6 +1572,10 @@ describe('Scope', function() { | |
}); | ||
grandChild.$emit('myEvent'); | ||
expect(event).toBeDefined(); | ||
|
||
// Asynchronous expectation : current & target should be the same as above | ||
expect(event.targetScope).toBe(grandChild); | ||
expect(event.currentScope).toBe(child); | ||
}); | ||
|
||
|
||
|
@@ -1693,26 +1697,41 @@ describe('Scope', function() { | |
expect(result.name).toBe('some'); | ||
expect(result.targetScope).toBe(child1); | ||
}); | ||
|
||
it('should have preventDefault method and defaultPrevented property', function() { | ||
var event = child2.$broadcast('myEvent'); | ||
expect(event.defaultPrevented).toBe(false); | ||
|
||
grandChild21.$on('myEvent', function(event) { | ||
event.preventDefault(); | ||
}); | ||
event = child2.$broadcast('myEvent'); | ||
expect(event.defaultPrevented).toBe(true); | ||
}); | ||
|
||
}); | ||
|
||
|
||
describe('listener', function() { | ||
it('should receive event object', inject(function($rootScope) { | ||
var scope = $rootScope, | ||
child = scope.$new(), | ||
grandChild = child.$new(), | ||
event; | ||
|
||
child.$on('fooEvent', function(e) { | ||
expect(e.targetScope).toBe(scope); | ||
expect(e.currentScope).toBe(child); | ||
expect(e.name).toBe('fooEvent'); | ||
event = e; | ||
}); | ||
scope.$broadcast('fooEvent'); | ||
|
||
expect(event.name).toBe('fooEvent'); | ||
// Asynchronous expectation : current & target should be the same as above | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wat There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's not asynchronous, and you should not give the impression that it's asynchronous
That's a test case you wrote yourself, it's not present in angular core! Just remove the "Asynchronous expectation..." bit There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You understand that I'm referring to the comment, right? That scope event handler is not being called asynchronously, there is nothing asynchronous happening here, it's all within a single turn of the event loop There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oops. No, I didn't. Sorry for that. |
||
expect(event.targetScope).toBe(scope); | ||
expect(event.currentScope).toBe(child); | ||
})); | ||
|
||
|
||
it('should support passing messages as varargs', inject(function($rootScope) { | ||
var scope = $rootScope, | ||
child = scope.$new(), | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It defines a javascript class which is instantiated for each listener among the tree of scopes.
By this way, each listener received a dedicated event with a stable
currentScope
property.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But why does this class need a
preventDefault
? There is not action being taken there other then alteringthis.defaultPrevented
. This seems misleading to me.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I retained the existing
preventDefault
.I asked myself for the purpose of this property. Perhaps to be consistent with DOM events.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel it should be removed, this may have been a mistake in the angular api. Events without a native default should not have a preventDefault method. @lgalfaso thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think they should have
preventDefault
even when in the case of a$broadcast
it does nothingThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lgalfaso why? I don't believe it does anything for
$emit
either. Its just basically a misleadingnoop
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Fresheyeball the event used to have a function called
preventDefault
and that should not be removed, user may call it (even if it does nothing).In the case of
$emit
, callingpreventDefault
does prevent the event from going upThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lgalfaso thats even worse. Why would
preventDefault
bestopPropagation
? There is no browser default, so there should be no prevent default. That is exactly why this is bad.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Fresheyeball There are two things involved there
This PR is to fix an existing issue with events
current
parameter (that affects$broadcast
and$emit
). As part of this fix, it is required that this does not break what people expect from the API, this includes that there is a function calledpreventDefault
. How this function works is not part of this PR.Now,
preventDefault
is part of the DOM standard http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event-preventDefault. This patch is not about adding/removing or being consistent on the fact that there is apreventDefault
function and notstopPropagation
nor on the fact thatpreventDefault
works in one way when calling$broadcast
and in another way when calling$emit
. If you feel that this is a limitation you are welcome to put a PR in place