-
Notifications
You must be signed in to change notification settings - Fork 27.4k
fix($compile): do not rebind parent bound transclude functions #9605
Conversation
I'm sorry, but I wasn't able to verify your Contributor License Agreement (CLA) signature. CLA signature is required for any code contributions to AngularJS. Please sign our CLA and ensure that the CLA signature email address and the email address in this PR's commits match. If you signed the CLA as a corporation, please let us know the company's name. Thanks a bunch! PS: If you signed the CLA in the past then most likely the email addresses don't match. Please sign the CLA again or update the email address in the commit of this PR. |
@@ -1953,7 +1953,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { | |||
var transcludeControllers; | |||
|
|||
// No scope passed in: | |||
if (!isScope(scope)) { | |||
if (!isScope(scope) && !isUndefined(scope)) { |
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.
Do we still need this when we are not wrapping anything?
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.
Yes, it's still necessary, but not for the reason I originally thought. Let me take a closer look.
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 there may be a recursion case that its handling where there's still wrapping going on. I'll take another look when I get a chance.
Could you also change the docs for
|
Btw, the
|
Btw, I signed the CLA with an account that lists the same email address as my github account, so I'm not sure why mary-poppins is complaining. It isn't the primary email address, but it is listed. |
@tbosch, I was thinking that deprecating the |
3859ea0
to
4cdb797
Compare
Fixed the last case of wrapping ... there was some tricky recursion that wasn't handled before. |
@dlongley I see that you updated the PR for a fix but you did not added/modified any of the existing tests. Can you please add a test that shows this recursion case that you are talking about |
4cdb797
to
1011393
Compare
@lgalfaso, done. |
// a `controllersBoundTransclude` function, so prevent double-wrapping | ||
// by using the previously-wrapped boundTranscludeFn. | ||
var unwrappedFn = boundTranscludeFn.$$boundTransclude || boundTranscludeFn; | ||
controllersBoundTransclude.$$boundTransclude = unwrappedFn; |
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.
This second assign for $$boundTransclude
is not needed as we already did it above
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.
Fixing this.
Could you just add a second commit to this PR that adds the |
@@ -5124,6 +5124,122 @@ describe('$compile', function() { | |||
}); | |||
|
|||
|
|||
// see issue https://github.com/angular/angular.js/issues/9413 | |||
describe('passing a parent bound transclude function to the link ' + |
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.
Please think about how to simplify this test so that it only tests the changed behavior and is easier to understand?
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.
That is just a grouping for the two tests nested in it that are both related to passing a parent bound transclude function. Is that not a good summary title for those two tests?
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 was following the example below ("removing a transcluded element") that then has nested tests below it.
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.
Sorry, I did not mean the test suite but the tests themselves.
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.
E.g. do we need a directive with terminal
and priority
and another directive with isolate scope to test this?
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.
Ok, terminal
, priority
, and the isolate scope have been removed. The recursive directive test was added per @lgalfaso's request.
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.
And do we really need 2 directives to test this?
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 can reuse the toggle directive (instead of the recursive directive), but that may end up being less clear with double-toggling. What's being tested is recursive transclusion.
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 thought about this for a bit. I think the second directive is necessary to make clear what's being tested. This test is specifically for recursive transclusion, not for directive recursion.
Sorry about the CLA hickup, our process should verify you soon. |
Yeah, will do. |
1011393
to
83857c3
Compare
Thanks. Sorry, but this will probably have to wait until after ngEurope (2 weeks)... |
@tbosch, ok, thanks, no problem. Just wanted to be clear that I think it's ready when you guys are. |
4dd5a20
to
998c61c
Compare
76662bd
to
98f65da
Compare
@tbosch -- I've sorted out the conflicts with this PR and it's ready for auto-merging again. |
@tbosch, could this be merged now and make it into 1.3.2? |
}; | ||
}); | ||
directive('toggle', function() { | ||
return { |
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.
use valueFn({ ... your directive ... })
here to make it slightly smaller and easier to read (instead of function() { return { ... }; }
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.
Fixed.
98f65da
to
1b567f5
Compare
i said before, the fix looks good to me, but should probably get approval from tbosch |
children = children.concat(getChildScopes(childScope)); | ||
} while ((childScope = childScope.$$nextSibling)); | ||
return children; | ||
} |
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.
countScopes()
and getChildScopes()
are already available in this file. I will move the other copy and remove these.
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.
Igor is adding these to ngMock --- so I wouldn't worry about it. We should land Igor's PR for that though
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.
Landed #9871 --- please just use (Scope.$countChildScopes() + 1)
now
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.
Fixed.
1b567f5
to
bb4e94f
Compare
Do not rebind parent bound transclude functions passed to the link function returned from `$compile`. Change parameter order of ```publicLinkFn``` to allow parent bound transclude functions to be passed (do not make public yet). The current `$compile` public API documentation indicates that a transclude function may be passed as a second parameter, but it is not clear that this is not the same function that is given to directive link functions as the `transcludeFn` parameter. This parameter must be passed in order to implement, for example, lazy compilation. In order to pass the `transcludeFn` parameter given to a directive's link function, it must be passed to the result of a call to `$compile` (i.e. `publicLinkFn`). Doing so, however, would cause two bugs. First, the passed transclude function would get rebound, improperly changing its scope from its original binding. Second, the `containingScope` would not be updated and the wrong `$parent` would be assigned to the `transcludedScope` resulting in a memory leak. This patch fixes both of these issues. This patch does not expose a new public API for `publicLinkFn`, rather, it leaves this to a later change that better considers how that public API should look. Thanks to @lgalfaso, @tbosch, and @petebacondarwin. Related to angular#9413
Use `options` object hash style parameter for publicLinkFn. Expose `options` parameter as part of the public API. Closes angular#9413
bb4e94f
to
ff06bbd
Compare
Uses |
Gotcha! |
alright, I don't think the tests are really getting any simpler, which is too bad, but it's hard to do that with the compiler. LGTM |
Merging. |
I squashed the two commits into one because the first actually fails without the second and it was too complicated to try to work out which bits needed to be moved between the commits to get them both to pass. The change to the new ngMock helpers, I put into a separate commit. |
Awesome! Thanks, everyone. |
Landed as 841c090 |
Do not rebind parent bound transclude functions passed to the
link function returned from
$compile
. Change parameterorder of
publicLinkFn
to allow parent bound transcludefunctions to be passed (do not make public yet).
The current
$compile
public API documentation indicates thata transclude function may be passed as a second parameter, but
it is not clear that this is not the same function that is given
to directive link functions as the
transcludeFn
parameter. Thisparameter must be passed in order to implement, for example,
lazy compilation.
In order to pass the
transcludeFn
parameter given toa directive's link function, it must be passed to the
result of a call to
$compile
(i.e.publicLinkFn
). Doing so,however, would cause two bugs. First, the passed transclude
function would get rebound, improperly changing its scope
from its original binding. Second, the
containingScope
wouldnot be updated and the wrong
$parent
would be assigned tothe
transcludedScope
resulting in a memory leak. This patchfixes both of these issues.
This patch does not expose a new public API for
publicLinkFn
,rather, it leaves this to a later change that better considers
how that public API should look.
Thanks to @lgalfaso, @tbosch, and @petebacondarwin.
Related to #9413