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

Lazy/Eager $compile on transclusion changed behavior #13652

Closed
shlomiassaf opened this issue Dec 29, 2015 · 3 comments
Closed

Lazy/Eager $compile on transclusion changed behavior #13652

shlomiassaf opened this issue Dec 29, 2015 · 3 comments

Comments

@shlomiassaf
Copy link

Hi,

This is a tricky one to explain, I`ll do my best.

Using the ui-select angular 3rd party packages does not work with 1.5.0-rc.0

I believe its related to the Lazily compile the transclude function commit

Since its not a breaking API commit everything should work as before but ui-select fails.

I've debugged deeply into angular core and found that while compiling a directive angular will try to compile child directive, and a child directive in ui-select does not compile.

When a call to "compile" is invoked on the directive the behavior is now different.
Before lazy compilation a direct call to the compile function was made:

childTranscludeFn = compile($template, transcludeFn, terminalPriority,
  replaceDirective && replaceDirective.name, {
                                          // Don't pass in:
                                          // - controllerDirectives - otherwise we'll create duplicates controllers
                                          // - newIsolateScopeDirective or templateDirective - combining templates with
                                          //   element transclusion doesn't make sense.
                                          //
                                          // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
                                          // on the same element more than once.
                                          nonTlbTranscludeDirective: nonTlbTranscludeDirective
                                        });

Now, it is replaced with

childTranscludeFn = compilationGenerator(mightHaveMultipleTransclusionError, $template, transcludeFn, terminalPriority,
                                        replaceDirective && replaceDirective.name, {
                                          // Don't pass in:
                                          // - controllerDirectives - otherwise we'll create duplicates controllers
                                          // - newIsolateScopeDirective or templateDirective - combining templates with
                                          //   element transclusion doesn't make sense.
                                          //
                                          // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
                                          // on the same element more than once.
                                          nonTlbTranscludeDirective: nonTlbTranscludeDirective
                                        });

The latter will send a lazy instruction hence the returning function will be a compilation invoker rather then the result of the compilation. Stepping further reveals that the compilation invoker function never gets invoked.

Again, very tricky and complex.
Whats more strange is that I have tried to mimic ui-select's behavior on simple directives with no success, I cant mimic it for some reason.

I believe that the protection implemented to prevent this case does not cover all use cases.

        if (!didScanForMultipleTransclusion && ((directive.replace && (directive.templateUrl || directive.template))
            || (directive.transclude && !directive.$$tlb))) {
                var candidateDirective;

                for (var scanningIndex = i + 1; candidateDirective = directives[scanningIndex++];) {
                    if ((candidateDirective.transclude && !candidateDirective.$$tlb)
                        || (candidateDirective.replace && (candidateDirective.templateUrl || candidateDirective.template))) {
                        mightHaveMultipleTransclusionError = true;
                        break;
                    }
                }

                didScanForMultipleTransclusion = true;
        }

I debugged it and it yielded false, hence lazy compilation implemented.

See my issue on angular-ui/ui-select#1372 for extra info

I dont know where the issue is but I guess its in angular.js since it broke an old working implementation.

@shlomiassaf
Copy link
Author

@dcherman
@lgalfaso

@lgalfaso
Copy link
Contributor

this looks like a duplicate of #13527 and the issue opened on ui-select looks like a duplicate of angular-ui/ui-select#1356

Now, that said, it looks like the issue is a race condition within ui-select as it is possible to reproduce the issue with 1.4 #13527 (comment)

@shlomiassaf
Copy link
Author

👍

Spent some 2-3 hours on that but learned a lot about the transclusion core behavior.

# for free to subscribe to this conversation on GitHub. Already have an account? #.
Projects
None yet
Development

No branches or pull requests

3 participants