@angular-wave/angular.ts 0.9.3 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/@types/angular.d.ts +4 -19
- package/@types/animations/animate.d.ts +2 -2
- package/@types/animations/animation.d.ts +1 -1
- package/@types/core/compile/attributes.d.ts +1 -1
- package/@types/core/compile/compile.d.ts +2 -2
- package/@types/core/controller/controller.d.ts +1 -1
- package/@types/core/controller/interface.d.ts +6 -0
- package/@types/core/di/ng-module.d.ts +27 -26
- package/@types/core/filter/filter.d.ts +5 -5
- package/@types/core/interpolate/interface.d.ts +13 -0
- package/@types/core/interpolate/interpolate.d.ts +1 -13
- package/@types/core/scope/scope.d.ts +4 -1
- package/@types/directive/http/http.d.ts +16 -16
- package/@types/directive/http/interface.d.ts +27 -0
- package/@types/directive/include/include.d.ts +4 -4
- package/@types/directive/inject/inject.d.ts +12 -0
- package/@types/directive/model/model.d.ts +1 -1
- package/@types/directive/script/script.d.ts +2 -2
- package/@types/directive/setter/setter.d.ts +4 -4
- package/@types/filters/filter.d.ts +2 -2
- package/@types/filters/filters.d.ts +2 -2
- package/@types/filters/interface.d.ts +8 -0
- package/@types/filters/limit-to.d.ts +2 -2
- package/@types/filters/order-by.d.ts +2 -2
- package/@types/interface.d.ts +105 -82
- package/@types/namespace.d.ts +76 -0
- package/@types/router/state/interface.d.ts +8 -8
- package/@types/router/state-filters.d.ts +4 -4
- package/@types/router/template-factory.d.ts +8 -8
- package/@types/router/transition/hook-builder.d.ts +5 -2
- package/@types/router/transition/hook-registry.d.ts +11 -2
- package/@types/router/transition/transition-service.d.ts +6 -2
- package/@types/router/transition/transition.d.ts +2 -2
- package/@types/router/view/view.d.ts +1 -8
- package/@types/router/view-scroll.d.ts +4 -2
- package/@types/services/{anchor-scroll.d.ts → anchor-scroll/anchor-scroll.d.ts} +2 -2
- package/@types/services/exception/exception-handler.d.ts +2 -2
- package/@types/services/exception/interface.d.ts +1 -1
- package/@types/services/http/http.d.ts +40 -2
- package/@types/services/http/interface.d.ts +11 -0
- package/@types/services/location/location.d.ts +1 -4
- package/@types/services/sce/sce.d.ts +3 -4
- package/@types/services/template-cache/template-cache.d.ts +4 -4
- package/@types/services/template-request/interface.d.ts +22 -0
- package/@types/services/{template-request.d.ts → template-request/template-request.d.ts} +4 -7
- package/@types/shared/common.d.ts +8 -69
- package/@types/shared/hof.d.ts +7 -7
- package/dist/angular-ts.esm.js +510 -570
- package/dist/angular-ts.umd.js +510 -570
- package/dist/angular-ts.umd.min.js +1 -1
- package/package.json +8 -1
- package/.github/workflows/ci.yml +0 -104
- package/.github/workflows/gh-pages.yml +0 -75
- package/.husky/pre-commit +0 -5
- package/.prettierignore +0 -9
- package/@types/services/cookie-reader.d.ts +0 -4
- package/@types/services/http-backend/http-backend.d.ts +0 -58
- package/@types/services/template-cache/interface.d.ts +0 -10
- package/CHANGELOG.md +0 -17667
- package/CODE_OF_CONDUCT.md +0 -3
- package/CONTRIBUTING.md +0 -247
- package/DEVELOPERS.md +0 -499
- package/Makefile +0 -60
- package/RELEASE.md +0 -86
- package/TRIAGING.md +0 -127
- package/docs/.cspell.yml +0 -8
- package/docs/.github/dependabot.yml +0 -14
- package/docs/.nvmrc +0 -1
- package/docs/CONTRIBUTING.md +0 -28
- package/docs/Dockerfile +0 -4
- package/docs/LICENSE +0 -201
- package/docs/README.md +0 -217
- package/docs/assets/icons/logo.svg +0 -1
- package/docs/assets/scss/_variables_project.scss +0 -12
- package/docs/assets/scss/_variables_project_after_bs.scss +0 -8
- package/docs/assets/scss/index.scss +0 -48
- package/docs/config.yaml +0 -15
- package/docs/content/_index.md +0 -28
- package/docs/content/docs/_index.md +0 -61
- package/docs/content/docs/directive/_index.md +0 -4
- package/docs/content/docs/directive/app.md +0 -11
- package/docs/content/docs/directive/aria.md +0 -0
- package/docs/content/docs/directive/bind.md +0 -72
- package/docs/content/docs/directive/blur.md +0 -38
- package/docs/content/docs/directive/channel.md +0 -37
- package/docs/content/docs/directive/class-even.md +0 -47
- package/docs/content/docs/directive/class-odd.md +0 -48
- package/docs/content/docs/directive/class.md +0 -64
- package/docs/content/docs/directive/click.md +0 -41
- package/docs/content/docs/directive/cloak.md +0 -74
- package/docs/content/docs/directive/copy.md +0 -38
- package/docs/content/docs/directive/cut.md +0 -40
- package/docs/content/docs/directive/dblclick.md +0 -41
- package/docs/content/docs/directive/focus.md +0 -38
- package/docs/content/docs/directive/get.md +0 -203
- package/docs/content/docs/directive/include.md +0 -7
- package/docs/content/docs/directive/keydown.md +0 -38
- package/docs/content/docs/directive/keyup.md +0 -38
- package/docs/content/docs/directive/load.md +0 -43
- package/docs/content/docs/directive/mousedown.md +0 -38
- package/docs/content/docs/directive/mouseenter.md +0 -38
- package/docs/content/docs/directive/mouseleave.md +0 -38
- package/docs/content/docs/directive/mousemove.md +0 -38
- package/docs/content/docs/directive/mouseout.md +0 -38
- package/docs/content/docs/directive/mouseover.md +0 -38
- package/docs/content/docs/directive/mouseup.md +0 -38
- package/docs/content/docs/directive/non-bindable.md +0 -28
- package/docs/content/docs/filter/_index.md +0 -4
- package/docs/content/docs/provider/_index.md +0 -4
- package/docs/content/docs/provider/eventBusProvider.md +0 -35
- package/docs/content/docs/provider/locationProvider.md +0 -26
- package/docs/content/docs/provider/logProvider.md +0 -59
- package/docs/content/docs/provider/templateCacheProvider.md +0 -100
- package/docs/content/docs/service/_index.md +0 -4
- package/docs/content/docs/service/eventBus.md +0 -56
- package/docs/content/docs/service/location.md +0 -57
- package/docs/content/docs/service/log.md +0 -113
- package/docs/content/docs/service/templateCache.md +0 -64
- package/docs/content/docs/service/url.md +0 -5
- package/docs/docker-compose.yaml +0 -12
- package/docs/docsy.work +0 -5
- package/docs/docsy.work.sum +0 -0
- package/docs/go.mod +0 -5
- package/docs/go.sum +0 -6
- package/docs/hugo-disabled.toml +0 -220
- package/docs/hugo.yaml +0 -200
- package/docs/layouts/404.html +0 -13
- package/docs/layouts/_markup/render-heading.html +0 -1
- package/docs/layouts/partials/hooks/head-end.html +0 -3
- package/docs/layouts/shortcodes/showcss.html +0 -2
- package/docs/layouts/shortcodes/showhtml.html +0 -2
- package/docs/layouts/shortcodes/showjs.html +0 -2
- package/docs/layouts/shortcodes/showraw.html +0 -1
- package/docs/layouts/shortcodes/version.html +0 -1
- package/docs/package-lock.json +0 -2293
- package/docs/package.json +0 -53
- package/docs/static/examples/counter/counter-test.html +0 -13
- package/docs/static/examples/counter/counter.html +0 -5
- package/docs/static/examples/counter/counter.test.js +0 -28
- package/docs/static/examples/eventbus/eventbus-test.html +0 -15
- package/docs/static/examples/eventbus/eventbus.html +0 -13
- package/docs/static/examples/eventbus/eventbus.js +0 -15
- package/docs/static/examples/eventbus/eventbus.test.js +0 -19
- package/docs/static/examples/ng-bind/ng-bind.html +0 -9
- package/docs/static/examples/ng-blur/ng-blur.html +0 -9
- package/docs/static/examples/ng-channel/ng-channel-test.html +0 -17
- package/docs/static/examples/ng-channel/ng-channel.html +0 -24
- package/docs/static/examples/ng-channel/ng-channel.test.js +0 -31
- package/docs/static/examples/ng-class/ng-class.html +0 -71
- package/docs/static/examples/ng-class-even/ng-class-even.html +0 -8
- package/docs/static/examples/ng-class-odd/ng-class-odd.html +0 -8
- package/docs/static/examples/ng-click/ng-click.html +0 -6
- package/docs/static/examples/ng-copy/ng-copy.html +0 -6
- package/docs/static/examples/ng-cut/ng-cut.html +0 -6
- package/docs/static/examples/ng-dblclick/ng-dblclick.html +0 -10
- package/docs/static/examples/ng-focus/ng-focus.html +0 -9
- package/docs/static/examples/ng-keydown/ng-keydown.html +0 -9
- package/docs/static/examples/ng-keyup/ng-keyup.html +0 -9
- package/docs/static/examples/ng-load/ng-load.html +0 -8
- package/docs/static/examples/ng-mousedown/ng-mousedown.html +0 -6
- package/docs/static/examples/ng-mouseenter/ng-mouseenter.html +0 -4
- package/docs/static/examples/ng-mouseleave/ng-mouseleave.html +0 -4
- package/docs/static/examples/ng-mousemove/ng-mousemove.html +0 -4
- package/docs/static/examples/ng-mouseout/ng-mouseout.html +0 -4
- package/docs/static/examples/ng-mouseover/ng-mouseover.html +0 -4
- package/docs/static/examples/ng-mouseup/ng-mouseup.html +0 -4
- package/docs/static/examples/ng-non-bindable/ng-non-bindable-test.html +0 -13
- package/docs/static/examples/ng-non-bindable/ng-non-bindable.html +0 -3
- package/docs/static/examples/ng-non-bindable/ng-non-bindable.test.js +0 -11
- package/docs/static/typedoc/.nojekyll +0 -1
- package/docs/static/typedoc/assets/hierarchy.js +0 -1
- package/docs/static/typedoc/assets/highlight.css +0 -78
- package/docs/static/typedoc/assets/icons.js +0 -18
- package/docs/static/typedoc/assets/icons.svg +0 -1
- package/docs/static/typedoc/assets/main.js +0 -60
- package/docs/static/typedoc/assets/navigation.js +0 -1
- package/docs/static/typedoc/assets/search.js +0 -1
- package/docs/static/typedoc/assets/style.css +0 -1633
- package/docs/static/typedoc/classes/Location.html +0 -55
- package/docs/static/typedoc/classes/LocationProvider.html +0 -20
- package/docs/static/typedoc/classes/LogProvider.html +0 -6
- package/docs/static/typedoc/classes/PubSub.html +0 -71
- package/docs/static/typedoc/classes/PubSubProvider.html +0 -3
- package/docs/static/typedoc/classes/TemplateCacheProvider.html +0 -5
- package/docs/static/typedoc/hierarchy.html +0 -1
- package/docs/static/typedoc/index.html +0 -1
- package/docs/static/typedoc/interfaces/ChangesObject.html +0 -6
- package/docs/static/typedoc/interfaces/ComponentOptions.html +0 -16
- package/docs/static/typedoc/interfaces/Controller.html +0 -12
- package/docs/static/typedoc/interfaces/DefaultPorts.html +0 -5
- package/docs/static/typedoc/interfaces/Directive.html +0 -37
- package/docs/static/typedoc/interfaces/DirectivePrePost.html +0 -4
- package/docs/static/typedoc/interfaces/Html5Mode.html +0 -23
- package/docs/static/typedoc/interfaces/HttpHeadersGetter.html +0 -1
- package/docs/static/typedoc/interfaces/HttpProviderDefaults.html +0 -31
- package/docs/static/typedoc/interfaces/HttpRequestConfigHeaders.html +0 -6
- package/docs/static/typedoc/interfaces/HttpRequestTransformer.html +0 -1
- package/docs/static/typedoc/interfaces/HttpResponse.html +0 -7
- package/docs/static/typedoc/interfaces/HttpResponseTransformer.html +0 -1
- package/docs/static/typedoc/interfaces/HttpService.html +0 -38
- package/docs/static/typedoc/interfaces/LogService.html +0 -12
- package/docs/static/typedoc/interfaces/NgModelController.html +0 -30
- package/docs/static/typedoc/interfaces/NgModelOptions.html +0 -16
- package/docs/static/typedoc/interfaces/Provider.html +0 -34
- package/docs/static/typedoc/interfaces/RequestConfig.html +0 -48
- package/docs/static/typedoc/interfaces/RequestShortcutConfig.html +0 -38
- package/docs/static/typedoc/interfaces/ServiceProvider.html +0 -5
- package/docs/static/typedoc/interfaces/TemplateCache.html +0 -7
- package/docs/static/typedoc/interfaces/TranscludeFunctionObject.html +0 -8
- package/docs/static/typedoc/interfaces/UrlParts.html +0 -9
- package/docs/static/typedoc/types/AnnotatedDirectiveFactory.html +0 -1
- package/docs/static/typedoc/types/AnnotatedFactory.html +0 -8
- package/docs/static/typedoc/types/CloneAttachFunction.html +0 -2
- package/docs/static/typedoc/types/ControllerConstructor.html +0 -2
- package/docs/static/typedoc/types/DirectiveCompileFn.html +0 -2
- package/docs/static/typedoc/types/DirectiveController.html +0 -2
- package/docs/static/typedoc/types/DirectiveFactory.html +0 -1
- package/docs/static/typedoc/types/DirectiveFactoryFn.html +0 -1
- package/docs/static/typedoc/types/DirectiveLinkFn.html +0 -2
- package/docs/static/typedoc/types/ExpandoStore.html +0 -2
- package/docs/static/typedoc/types/Expression.html +0 -6
- package/docs/static/typedoc/types/FilterFactory.html +0 -2
- package/docs/static/typedoc/types/FilterFn.html +0 -2
- package/docs/static/typedoc/types/HttpPromise.html +0 -1
- package/docs/static/typedoc/types/HttpResponseStatus.html +0 -1
- package/docs/static/typedoc/types/Injectable.html +0 -4
- package/docs/static/typedoc/types/InjectableClass.html +0 -1
- package/docs/static/typedoc/types/InjectableFactory.html +0 -1
- package/docs/static/typedoc/types/LogCall.html +0 -2
- package/docs/static/typedoc/types/LogServiceFactory.html +0 -2
- package/docs/static/typedoc/types/OnChangesObject.html +0 -2
- package/docs/static/typedoc/types/SwapModeType.html +0 -2
- package/docs/static/typedoc/types/TController.html +0 -2
- package/docs/static/typedoc/types/UrlChangeListener.html +0 -5
- package/docs/static/typedoc/variables/EventBus.html +0 -1
- package/docs/static/typedoc/variables/SwapMode.html +0 -11
- package/docs/static/version.js +0 -13
- package/docs/test-results/.last-run.json +0 -4
- package/docs/test-results/static-examples-counter-counter-counter-example/error-context.md +0 -50
- package/eslint.config.js +0 -26
- package/images/android-chrome-192x192.png +0 -0
- package/images/android-chrome-512x512.png +0 -0
- package/images/apple-touch-icon.png +0 -0
- package/images/favicon-16x16.png +0 -0
- package/images/favicon-32x32.png +0 -0
- package/images/favicon.ico +0 -0
- package/images/site.webmanifest +0 -19
- package/index.html +0 -86
- package/legacy.d.ts +0 -2599
- package/playwright.config.ts +0 -81
- package/public/jasmine/boot0.js +0 -66
- package/public/jasmine/boot1.js +0 -134
- package/public/jasmine/jasmine-html.js +0 -970
- package/public/jasmine/jasmine.css +0 -323
- package/public/jasmine/jasmine.js +0 -11406
- package/public/public/README.md +0 -1
- package/public/public/circle.html +0 -1
- package/public/public/jasmine-helper.css +0 -9
- package/public/public/my_child_directive.html +0 -1
- package/public/public/my_directive.html +0 -1
- package/public/public/my_other_directive.html +0 -1
- package/public/public/test.html +0 -1
- package/rollup.config.js +0 -51
- package/src/angular.js +0 -293
- package/src/angular.spec.js +0 -1191
- package/src/animations/animate-cache.js +0 -80
- package/src/animations/animate-children-directive.js +0 -32
- package/src/animations/animate-children-directive.md +0 -80
- package/src/animations/animate-css-driver.js +0 -284
- package/src/animations/animate-css.html +0 -58
- package/src/animations/animate-css.js +0 -915
- package/src/animations/animate-css.md +0 -263
- package/src/animations/animate-js-driver.js +0 -60
- package/src/animations/animate-js.html +0 -47
- package/src/animations/animate-js.js +0 -371
- package/src/animations/animate-queue.js +0 -859
- package/src/animations/animate-runner.js +0 -193
- package/src/animations/animate-swap.js +0 -33
- package/src/animations/animate-swap.md +0 -88
- package/src/animations/animate.html +0 -19
- package/src/animations/animate.js +0 -546
- package/src/animations/animate.md +0 -933
- package/src/animations/animate.spec.js +0 -490
- package/src/animations/animation.js +0 -519
- package/src/animations/animations.test.js +0 -10
- package/src/animations/interface.ts +0 -19
- package/src/animations/raf-scheduler.html +0 -19
- package/src/animations/raf-scheduler.js +0 -92
- package/src/animations/raf-scheduler.spec.js +0 -98
- package/src/animations/shared.js +0 -341
- package/src/binding.html +0 -19
- package/src/binding.spec.js +0 -474
- package/src/binding.test.js +0 -10
- package/src/core/compile/attributes.js +0 -337
- package/src/core/compile/compile.html +0 -19
- package/src/core/compile/compile.js +0 -3270
- package/src/core/compile/compile.md +0 -1128
- package/src/core/compile/compile.spec.js +0 -15574
- package/src/core/compile/compile.test.js +0 -12
- package/src/core/controller/controller.html +0 -22
- package/src/core/controller/controller.js +0 -189
- package/src/core/controller/controller.spec.js +0 -334
- package/src/core/controller/controller.test.js +0 -12
- package/src/core/core.html +0 -20
- package/src/core/core.test.js +0 -12
- package/src/core/di/injector.html +0 -19
- package/src/core/di/injector.js +0 -307
- package/src/core/di/injector.md +0 -740
- package/src/core/di/injector.spec.js +0 -2310
- package/src/core/di/injector.test.js +0 -12
- package/src/core/di/internal-injector.js +0 -284
- package/src/core/di/ng-module.html +0 -19
- package/src/core/di/ng-module.js +0 -226
- package/src/core/di/ng-module.spec.js +0 -263
- package/src/core/di/ng-module.test.js +0 -12
- package/src/core/filter/filter.html +0 -19
- package/src/core/filter/filter.js +0 -55
- package/src/core/filter/filter.md +0 -132
- package/src/core/filter/filter.spec.js +0 -149
- package/src/core/filter/filter.test.js +0 -12
- package/src/core/interpolate/interpolate.html +0 -22
- package/src/core/interpolate/interpolate.js +0 -408
- package/src/core/interpolate/interpolate.spec.js +0 -601
- package/src/core/interpolate/interpolate.test.js +0 -12
- package/src/core/parse/ast/ast-node.ts +0 -81
- package/src/core/parse/ast/ast.html +0 -19
- package/src/core/parse/ast/ast.js +0 -574
- package/src/core/parse/ast/ast.spec.js +0 -1453
- package/src/core/parse/ast/ast.test.js +0 -10
- package/src/core/parse/ast-type.js +0 -23
- package/src/core/parse/interface.ts +0 -84
- package/src/core/parse/interpreter.js +0 -915
- package/src/core/parse/lexer/lexer.html +0 -19
- package/src/core/parse/lexer/lexer.js +0 -338
- package/src/core/parse/lexer/lexer.spec.js +0 -303
- package/src/core/parse/lexer/lexer.test.js +0 -10
- package/src/core/parse/lexer/token.ts +0 -22
- package/src/core/parse/parse.html +0 -19
- package/src/core/parse/parse.js +0 -337
- package/src/core/parse/parse.md +0 -57
- package/src/core/parse/parse.spec.js +0 -2107
- package/src/core/parse/parse.test.js +0 -10
- package/src/core/parse/parser/parser.html +0 -19
- package/src/core/parse/parser/parser.js +0 -64
- package/src/core/parse/parser/parser.spec.js +0 -8
- package/src/core/parse/parser/parser.test.js +0 -10
- package/src/core/prop.spec.js +0 -775
- package/src/core/root-element.spec.js +0 -14
- package/src/core/sanitize/interface.ts +0 -10
- package/src/core/sanitize/sanitize-uri.js +0 -75
- package/src/core/sanitize/sanitize-uri.spec.js +0 -249
- package/src/core/sanitize/sanitize-uri.test.js +0 -12
- package/src/core/sanitize/sanitize.html +0 -22
- package/src/core/scope/scope.html +0 -19
- package/src/core/scope/scope.js +0 -1249
- package/src/core/scope/scope.spec.js +0 -3000
- package/src/core/scope/scope.test.js +0 -12
- package/src/directive/aria/aria.html +0 -19
- package/src/directive/aria/aria.js +0 -382
- package/src/directive/aria/aria.md +0 -145
- package/src/directive/aria/aria.spec.js +0 -1241
- package/src/directive/aria/aria.test.js +0 -12
- package/src/directive/attrs/attrs.html +0 -19
- package/src/directive/attrs/attrs.js +0 -106
- package/src/directive/attrs/attrs.md +0 -224
- package/src/directive/attrs/attrs.spec.js +0 -71
- package/src/directive/attrs/attrs.test.js +0 -12
- package/src/directive/attrs/boolean.html +0 -19
- package/src/directive/attrs/boolean.spec.js +0 -137
- package/src/directive/attrs/boolean.test.js +0 -12
- package/src/directive/attrs/element-style.html +0 -22
- package/src/directive/attrs/element-style.spec.js +0 -85
- package/src/directive/attrs/element-style.test.js +0 -12
- package/src/directive/attrs/src.html +0 -19
- package/src/directive/attrs/src.spec.js +0 -163
- package/src/directive/attrs/src.test.js +0 -12
- package/src/directive/bind/bind-html.spec.js +0 -36
- package/src/directive/bind/bind.html +0 -20
- package/src/directive/bind/bind.js +0 -78
- package/src/directive/bind/bind.md +0 -142
- package/src/directive/bind/bind.spec.js +0 -314
- package/src/directive/bind/bind.test.js +0 -12
- package/src/directive/channel/channel.html +0 -19
- package/src/directive/channel/channel.js +0 -30
- package/src/directive/channel/channel.spec.js +0 -67
- package/src/directive/channel/channel.test.js +0 -10
- package/src/directive/class/class-test.html +0 -23
- package/src/directive/class/class.html +0 -19
- package/src/directive/class/class.js +0 -184
- package/src/directive/class/class.spec.js +0 -704
- package/src/directive/class/class.test.js +0 -12
- package/src/directive/cloak/cloak.html +0 -19
- package/src/directive/cloak/cloak.js +0 -11
- package/src/directive/cloak/cloak.spec.js +0 -44
- package/src/directive/cloak/cloak.test.js +0 -12
- package/src/directive/controller/controller.html +0 -22
- package/src/directive/controller/controller.js +0 -11
- package/src/directive/controller/controller.md +0 -46
- package/src/directive/controller/controller.spec.js +0 -175
- package/src/directive/controller/controller.test.js +0 -12
- package/src/directive/events/click.spec.js +0 -35
- package/src/directive/events/event.spec.js +0 -267
- package/src/directive/events/events-test.html +0 -36
- package/src/directive/events/events.html +0 -20
- package/src/directive/events/events.js +0 -65
- package/src/directive/events/events.md +0 -125
- package/src/directive/events/events.test.js +0 -12
- package/src/directive/form/form.html +0 -19
- package/src/directive/form/form.js +0 -669
- package/src/directive/form/form.spec.js +0 -1515
- package/src/directive/form/form.test.js +0 -12
- package/src/directive/http/delete.spec.js +0 -26
- package/src/directive/http/form-router-test.html +0 -44
- package/src/directive/http/form-test.html +0 -18
- package/src/directive/http/get.spec.js +0 -488
- package/src/directive/http/http.html +0 -22
- package/src/directive/http/http.js +0 -342
- package/src/directive/http/http.test.js +0 -12
- package/src/directive/http/post-example.html +0 -30
- package/src/directive/http/post.spec.js +0 -521
- package/src/directive/http/put.spec.js +0 -26
- package/src/directive/if/if-animate-css.html +0 -57
- package/src/directive/if/if-animate-svg.html +0 -25
- package/src/directive/if/if.html +0 -19
- package/src/directive/if/if.js +0 -72
- package/src/directive/if/if.md +0 -76
- package/src/directive/if/if.spec.js +0 -293
- package/src/directive/if/if.test.js +0 -114
- package/src/directive/include/include.html +0 -19
- package/src/directive/include/include.js +0 -151
- package/src/directive/include/include.md +0 -87
- package/src/directive/include/include.spec.js +0 -734
- package/src/directive/include/include.test.js +0 -12
- package/src/directive/init/init.html +0 -19
- package/src/directive/init/init.js +0 -22
- package/src/directive/init/init.md +0 -41
- package/src/directive/init/init.spec.js +0 -68
- package/src/directive/init/init.test.js +0 -12
- package/src/directive/input/input-example.html +0 -15
- package/src/directive/input/input.html +0 -19
- package/src/directive/input/input.js +0 -1078
- package/src/directive/input/input.md +0 -706
- package/src/directive/input/input.spec.js +0 -3700
- package/src/directive/input/input.test.js +0 -12
- package/src/directive/messages/messages.html +0 -22
- package/src/directive/messages/messages.js +0 -349
- package/src/directive/messages/messages.md +0 -543
- package/src/directive/messages/messages.spec.js +0 -1083
- package/src/directive/messages/messages.test.js +0 -12
- package/src/directive/model/change.md +0 -25
- package/src/directive/model/model.html +0 -19
- package/src/directive/model/model.js +0 -1170
- package/src/directive/model/model.spec.js +0 -1976
- package/src/directive/model/model.test.js +0 -12
- package/src/directive/model-options/model-option.test.js +0 -12
- package/src/directive/model-options/model-options.html +0 -22
- package/src/directive/model-options/model-options.js +0 -142
- package/src/directive/model-options/model-options.md +0 -407
- package/src/directive/model-options/model-options.spec.js +0 -1022
- package/src/directive/non-bindable/non-bindable.html +0 -22
- package/src/directive/non-bindable/non-bindable.js +0 -9
- package/src/directive/non-bindable/non-bindable.spec.js +0 -59
- package/src/directive/non-bindable/non-bindable.test.js +0 -12
- package/src/directive/observe/observe-demo.html +0 -184
- package/src/directive/observe/observe.html +0 -19
- package/src/directive/observe/observe.js +0 -41
- package/src/directive/observe/observe.spec.js +0 -106
- package/src/directive/observe/observe.test.js +0 -10
- package/src/directive/on/on.html +0 -19
- package/src/directive/on/on.spec.js +0 -215
- package/src/directive/on/on.test.js +0 -12
- package/src/directive/options/options-example.html +0 -17
- package/src/directive/options/options.html +0 -22
- package/src/directive/options/options.js +0 -542
- package/src/directive/options/options.md +0 -179
- package/src/directive/options/options.spec.js +0 -3554
- package/src/directive/options/options.test.js +0 -12
- package/src/directive/ref/href.html +0 -19
- package/src/directive/ref/href.spec.js +0 -141
- package/src/directive/ref/href.test.js +0 -19
- package/src/directive/ref/ref.html +0 -19
- package/src/directive/ref/ref.js +0 -89
- package/src/directive/ref/ref.spec.js +0 -546
- package/src/directive/repeat/repeat.html +0 -19
- package/src/directive/repeat/repeat.js +0 -333
- package/src/directive/repeat/repeat.md +0 -330
- package/src/directive/repeat/repeat.spec.js +0 -1209
- package/src/directive/repeat/repeat.test.js +0 -12
- package/src/directive/script/script.html +0 -19
- package/src/directive/script/script.js +0 -17
- package/src/directive/script/script.md +0 -11
- package/src/directive/script/script.spec.js +0 -47
- package/src/directive/script/script.test.js +0 -12
- package/src/directive/select/select.html +0 -19
- package/src/directive/select/select.js +0 -594
- package/src/directive/select/select.md +0 -74
- package/src/directive/select/select.spec.js +0 -2566
- package/src/directive/select/select.test.js +0 -12
- package/src/directive/setter/setter.html +0 -19
- package/src/directive/setter/setter.js +0 -59
- package/src/directive/setter/setter.spec.js +0 -100
- package/src/directive/setter/setter.test.js +0 -12
- package/src/directive/show-hide/show-hide.html +0 -22
- package/src/directive/show-hide/show-hide.js +0 -65
- package/src/directive/show-hide/show-hide.md +0 -255
- package/src/directive/show-hide/show-hide.spec.js +0 -268
- package/src/directive/show-hide/show-hide.test.js +0 -12
- package/src/directive/style/style.html +0 -19
- package/src/directive/style/style.js +0 -27
- package/src/directive/style/style.md +0 -23
- package/src/directive/style/style.spec.js +0 -183
- package/src/directive/style/style.test.js +0 -12
- package/src/directive/switch/switch.html +0 -19
- package/src/directive/switch/switch.js +0 -133
- package/src/directive/switch/switch.md +0 -66
- package/src/directive/switch/switch.spec.js +0 -509
- package/src/directive/switch/switch.test.js +0 -12
- package/src/directive/transclude/transclude.js +0 -122
- package/src/directive/validators/validators.html +0 -22
- package/src/directive/validators/validators.js +0 -346
- package/src/directive/validators/validators.spec.js +0 -740
- package/src/directive/validators/validators.test.js +0 -12
- package/src/filters/filter.js +0 -213
- package/src/filters/filter.md +0 -69
- package/src/filters/filter.spec.js +0 -719
- package/src/filters/filters.html +0 -22
- package/src/filters/filters.js +0 -239
- package/src/filters/filters.spec.js +0 -36
- package/src/filters/filters.test.js +0 -12
- package/src/filters/json.md +0 -16
- package/src/filters/limit-to.js +0 -55
- package/src/filters/limit-to.md +0 -19
- package/src/filters/limit-to.spec.js +0 -252
- package/src/filters/order-by.js +0 -181
- package/src/filters/order-by.md +0 -83
- package/src/filters/order-by.spec.js +0 -883
- package/src/index.js +0 -6
- package/src/index.spec.js +0 -11
- package/src/injection-tokens.js +0 -78
- package/src/interface.ts +0 -421
- package/src/ng.js +0 -289
- package/src/ng.spec.js +0 -33
- package/src/router/common/trace.js +0 -240
- package/src/router/directives/component-example.html +0 -37
- package/src/router/directives/state-directives.html +0 -22
- package/src/router/directives/state-directives.js +0 -393
- package/src/router/directives/state-directives.md +0 -435
- package/src/router/directives/state-directives.spec.js +0 -1091
- package/src/router/directives/state-directives.test.js +0 -10
- package/src/router/directives/view-directive.js +0 -489
- package/src/router/directives/view-directive.spec.js +0 -1937
- package/src/router/directives/view-directive.test.js +0 -10
- package/src/router/directives/view-directives.html +0 -22
- package/src/router/glob/glob.html +0 -19
- package/src/router/glob/glob.js +0 -102
- package/src/router/glob/glob.spec.js +0 -108
- package/src/router/glob/glob.test.js +0 -12
- package/src/router/hooks/core-resolvables.js +0 -38
- package/src/router/hooks/ignored-transition.js +0 -25
- package/src/router/hooks/invalid-transition.js +0 -14
- package/src/router/hooks/lazy-load.js +0 -104
- package/src/router/hooks/on-enter-exit-retain.js +0 -55
- package/src/router/hooks/redirect-to.js +0 -38
- package/src/router/hooks/resolve.js +0 -57
- package/src/router/hooks/update-globals.js +0 -34
- package/src/router/hooks/url.js +0 -34
- package/src/router/hooks/views.js +0 -41
- package/src/router/params/interface.ts +0 -626
- package/src/router/params/param-factory.js +0 -23
- package/src/router/params/param-type.js +0 -133
- package/src/router/params/param-types.js +0 -153
- package/src/router/params/param.js +0 -243
- package/src/router/params/state-params.js +0 -36
- package/src/router/path/path-node.js +0 -78
- package/src/router/path/path-utils.js +0 -207
- package/src/router/resolve/interface.ts +0 -208
- package/src/router/resolve/resolvable.js +0 -123
- package/src/router/resolve/resolve-context.js +0 -190
- package/src/router/router-test-hashbang.html +0 -45
- package/src/router/router-test.html +0 -41
- package/src/router/router.html +0 -22
- package/src/router/router.js +0 -54
- package/src/router/router.test.js +0 -12
- package/src/router/services.spec.js +0 -52
- package/src/router/state/README.md +0 -21
- package/src/router/state/interface.ts +0 -1007
- package/src/router/state/state-builder.js +0 -376
- package/src/router/state/state-builder.spec.js +0 -86
- package/src/router/state/state-matcher.js +0 -64
- package/src/router/state/state-object.js +0 -118
- package/src/router/state/state-queue-manager.js +0 -95
- package/src/router/state/state-registry.js +0 -257
- package/src/router/state/state-service.js +0 -699
- package/src/router/state/state.html +0 -23
- package/src/router/state/state.spec.js +0 -1002
- package/src/router/state/state.test.js +0 -12
- package/src/router/state/target-state.js +0 -162
- package/src/router/state/views.js +0 -195
- package/src/router/state-filter.spec.js +0 -139
- package/src/router/state-filters.js +0 -46
- package/src/router/template-factory.html +0 -19
- package/src/router/template-factory.js +0 -249
- package/src/router/template-factory.spec.js +0 -155
- package/src/router/template-factory.test.js +0 -12
- package/src/router/transition/hook-builder.js +0 -133
- package/src/router/transition/hook-registry.js +0 -172
- package/src/router/transition/interface.js +0 -18
- package/src/router/transition/interface.ts +0 -922
- package/src/router/transition/reject-factory.js +0 -122
- package/src/router/transition/transition-event-type.js +0 -26
- package/src/router/transition/transition-hook.js +0 -199
- package/src/router/transition/transition-service.js +0 -302
- package/src/router/transition/transition.js +0 -652
- package/src/router/url/url-config.js +0 -155
- package/src/router/url/url-matcher.js +0 -532
- package/src/router/url/url-rule.js +0 -231
- package/src/router/url/url-rules.js +0 -350
- package/src/router/url/url-service.js +0 -446
- package/src/router/url/url-service.spec.js +0 -1288
- package/src/router/url/url.html +0 -19
- package/src/router/url/url.test.js +0 -12
- package/src/router/view/interface.ts +0 -51
- package/src/router/view/view.html +0 -19
- package/src/router/view/view.js +0 -274
- package/src/router/view/view.spec.js +0 -100
- package/src/router/view/view.test.js +0 -12
- package/src/router/view-hook.spec.js +0 -215
- package/src/router/view-scroll.js +0 -33
- package/src/router/view-scroll.spec.js +0 -72
- package/src/services/anchor-scroll.html +0 -76
- package/src/services/anchor-scroll.js +0 -147
- package/src/services/cookie-reader.js +0 -48
- package/src/services/exception/exception-handler.js +0 -75
- package/src/services/exception/interface.ts +0 -7
- package/src/services/http/http.html +0 -23
- package/src/services/http/http.js +0 -922
- package/src/services/http/http.md +0 -413
- package/src/services/http/http.spec.js +0 -3941
- package/src/services/http/http.test.js +0 -11
- package/src/services/http/interface.ts +0 -243
- package/src/services/http/template-request.spec.js +0 -220
- package/src/services/http-backend/http-backend.html +0 -22
- package/src/services/http-backend/http-backend.js +0 -158
- package/src/services/http-backend/http-backend.spec.js +0 -389
- package/src/services/http-backend/http-backend.test.js +0 -12
- package/src/services/location/interface.ts +0 -70
- package/src/services/location/location.html +0 -22
- package/src/services/location/location.js +0 -1006
- package/src/services/location/location.spec.js +0 -3792
- package/src/services/location/location.test.js +0 -12
- package/src/services/log/interface.ts +0 -39
- package/src/services/log/log.html +0 -19
- package/src/services/log/log.js +0 -74
- package/src/services/log/log.spec.js +0 -64
- package/src/services/log/log.test.js +0 -12
- package/src/services/pubsub/pubsub.html +0 -19
- package/src/services/pubsub/pubsub.js +0 -349
- package/src/services/pubsub/pubsub.spec.js +0 -400
- package/src/services/pubsub/pubsub.test.js +0 -12
- package/src/services/sce/sce.html +0 -19
- package/src/services/sce/sce.js +0 -847
- package/src/services/sce/sce.md +0 -300
- package/src/services/sce/sce.spec.js +0 -617
- package/src/services/sce/sce.test.js +0 -12
- package/src/services/template-cache/interface.ts +0 -10
- package/src/services/template-cache/template-cache.html +0 -22
- package/src/services/template-cache/template-cache.js +0 -15
- package/src/services/template-cache/template-cache.spec.js +0 -134
- package/src/services/template-cache/template-cache.test.js +0 -12
- package/src/services/template-request.js +0 -142
- package/src/shared/cache.js +0 -7
- package/src/shared/common.js +0 -438
- package/src/shared/common.spec.js +0 -294
- package/src/shared/constants.js +0 -21
- package/src/shared/dom.js +0 -716
- package/src/shared/hof.js +0 -151
- package/src/shared/hof.spec.js +0 -60
- package/src/shared/interface.ts +0 -21
- package/src/shared/min-err.spec.js +0 -178
- package/src/shared/noderef.js +0 -225
- package/src/shared/predicates.js +0 -34
- package/src/shared/queue.js +0 -105
- package/src/shared/queue.spec.js +0 -80
- package/src/shared/shared.html +0 -24
- package/src/shared/shared.test.js +0 -12
- package/src/shared/strings.js +0 -142
- package/src/shared/strings.spec.js +0 -40
- package/src/shared/test-utils.js +0 -47
- package/src/shared/url-utils/interface.ts +0 -54
- package/src/shared/url-utils/url-utils.html +0 -22
- package/src/shared/url-utils/url-utils.js +0 -122
- package/src/shared/url-utils/url-utils.spec.js +0 -148
- package/src/shared/url-utils/url-utils.test.js +0 -12
- package/src/shared/utils.js +0 -1255
- package/src/shared/utils.spec.js +0 -178
- package/src/src.html +0 -21
- package/src/src.test.js +0 -10
- package/tsconfig.json +0 -19
- package/tsconfig.types.json +0 -14
- package/typedoc.json +0 -8
- package/utils/express.js +0 -203
- package/utils/version.cjs +0 -23
- package/vite.config.js +0 -14
|
@@ -1,3270 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createElementFromHTML,
|
|
3
|
-
createNodelistFromHTML,
|
|
4
|
-
emptyElement,
|
|
5
|
-
getBooleanAttrName,
|
|
6
|
-
getCacheData,
|
|
7
|
-
getInheritedData,
|
|
8
|
-
isTextNode,
|
|
9
|
-
setCacheData,
|
|
10
|
-
setIsolateScope,
|
|
11
|
-
setScope,
|
|
12
|
-
startingTag,
|
|
13
|
-
} from "../../shared/dom.js";
|
|
14
|
-
import { NodeRef } from "../../shared/noderef.js";
|
|
15
|
-
import { identifierForController } from "../controller/controller.js";
|
|
16
|
-
import {
|
|
17
|
-
minErr,
|
|
18
|
-
assertArg,
|
|
19
|
-
assertNotHasOwnProperty,
|
|
20
|
-
isDefined,
|
|
21
|
-
isFunction,
|
|
22
|
-
isObject,
|
|
23
|
-
isString,
|
|
24
|
-
lowercase,
|
|
25
|
-
extend,
|
|
26
|
-
isScope,
|
|
27
|
-
inherit,
|
|
28
|
-
isUndefined,
|
|
29
|
-
getNodeName,
|
|
30
|
-
bind,
|
|
31
|
-
trim,
|
|
32
|
-
isBoolean,
|
|
33
|
-
equals,
|
|
34
|
-
simpleCompare,
|
|
35
|
-
isError,
|
|
36
|
-
directiveNormalize,
|
|
37
|
-
isProxy,
|
|
38
|
-
hasOwn,
|
|
39
|
-
} from "../../shared/utils.js";
|
|
40
|
-
import { SCE_CONTEXTS } from "../../services/sce/sce.js";
|
|
41
|
-
import { PREFIX_REGEXP } from "../../shared/constants.js";
|
|
42
|
-
import { createEventDirective } from "../../directive/events/events.js";
|
|
43
|
-
import { Attributes } from "./attributes.js";
|
|
44
|
-
import { ngObserveDirective } from "../../directive/observe/observe.js";
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* A function passed as the fifth argument to a {@type PublicLinkFn} link function.
|
|
48
|
-
* It behaves like a linking function, with the `scope` argument automatically created
|
|
49
|
-
* as a new child of the transcluded parent scope.
|
|
50
|
-
*
|
|
51
|
-
* The function returns the DOM content to be injected (transcluded) into the directive.
|
|
52
|
-
*
|
|
53
|
-
* @callback TranscludeFn
|
|
54
|
-
* @param {Element | Node | ChildNode | NodeList | Node[]} [clone] - The DOM node to be inserted into the transcluded directive.
|
|
55
|
-
* @param {import("../scope/scope.js").Scope} [scope] - The new child scope created from the transcluded parent.
|
|
56
|
-
* @returns void
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* A specialized version of {@link TranscludeFn} with the scope argument already bound.
|
|
60
|
-
* This function requires no parameters and returns the same result as {@link TranscludeFn}.
|
|
61
|
-
*
|
|
62
|
-
* @typedef {() => Element|Node} BoundTranscludeFn
|
|
63
|
-
*/
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* @typedef {Object} SimpleChange
|
|
67
|
-
* @property {any} currentValue
|
|
68
|
-
* @property {boolean} firstChange
|
|
69
|
-
*/
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* @description A function returned by the '$compile' service that links a compiled template to a scope.
|
|
73
|
-
*
|
|
74
|
-
* @callback PublicLinkFn
|
|
75
|
-
* @param {import('../scope/scope.js').Scope} scope - Scope to link with element
|
|
76
|
-
* @param {TranscludeFn} [cloneConnectFn]
|
|
77
|
-
* @param {*} [options]
|
|
78
|
-
* @return {Element|Node|ChildNode|Node[]} The nodes to be linked.
|
|
79
|
-
*/
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* @description Entry point for the '$compile' service.
|
|
83
|
-
*
|
|
84
|
-
* @callback CompileFn
|
|
85
|
-
* @param {string|Element|Node|ChildNode|NodeList} compileNode - The node to be compiled.
|
|
86
|
-
* @param {TranscludeFn} [transcludeFn] - An optional transclusion function to be used during compilation.
|
|
87
|
-
* @param {number} [maxPriority] - An optional maximum priority for directives.
|
|
88
|
-
* @param {string} [ignoreDirective] - An optional directive to ignore during compilation.
|
|
89
|
-
* @param {*} [previousCompileContext] - An optional context from a previous compilation. TODO
|
|
90
|
-
* @returns {PublicLinkFn} A public link function.
|
|
91
|
-
*/
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* @typedef {Object} LinkFnMapping
|
|
95
|
-
* @property {number} index
|
|
96
|
-
* @property {NodeLinkFnCtx} [nodeLinkFnCtx]
|
|
97
|
-
* @property {CompositeLinkFn} [childLinkFn]
|
|
98
|
-
*/
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* @typedef {function(): CompositeLinkFn} CompileNodesFn
|
|
102
|
-
*/
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* @callback NodeLinkFn
|
|
106
|
-
* @returns {Node|Element|NodeList}
|
|
107
|
-
*/
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* @typedef {Object} NodeLinkFnCtx
|
|
111
|
-
* @property {NodeLinkFn} nodeLinkFn
|
|
112
|
-
* @property {boolean} terminal
|
|
113
|
-
* @property {TranscludeFn} transclude
|
|
114
|
-
* @property {boolean} transcludeOnThisElement
|
|
115
|
-
* @property {boolean} templateOnThisElement
|
|
116
|
-
* @property {boolean} newScope
|
|
117
|
-
*/
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* @typedef {function(): NodeLinkFn} ApplyDirectivesToNodeFn
|
|
121
|
-
*/
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* @description Function that aggregates all linking fns for a compilation root (nodeList)
|
|
125
|
-
* @callback CompositeLinkFn
|
|
126
|
-
* @param {import('../scope/scope.js').Scope} scope - The scope to be linked to the template
|
|
127
|
-
* @param {NodeRef} $linkNode - wrapper around a nodeList
|
|
128
|
-
* @param {Function} [parentBoundTranscludeFn]
|
|
129
|
-
*/
|
|
130
|
-
|
|
131
|
-
const $compileMinErr = minErr("$compile");
|
|
132
|
-
const EXCLUDED_DIRECTIVES = ["ngIf", "ngRepeat"];
|
|
133
|
-
const ALL_OR_NOTHING_ATTRS = ["ngSrc", "ngSrcset", "src", "srcset"];
|
|
134
|
-
const REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/;
|
|
135
|
-
// Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
|
|
136
|
-
// The assumption is that future DOM event attribute names will begin with
|
|
137
|
-
// 'on' and be composed of only English letters.
|
|
138
|
-
const EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
|
|
139
|
-
export const DirectiveSuffix = "Directive";
|
|
140
|
-
|
|
141
|
-
export class CompileProvider {
|
|
142
|
-
/* @ignore */ static $inject = ["$provide", "$$sanitizeUriProvider"];
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* @param {import('../../interface.js').Provider} $provide
|
|
146
|
-
* @param {import('../sanitize/sanitize-uri.js').SanitizeUriProvider} $$sanitizeUriProvider
|
|
147
|
-
*/
|
|
148
|
-
constructor($provide, $$sanitizeUriProvider) {
|
|
149
|
-
const hasDirectives = {};
|
|
150
|
-
|
|
151
|
-
const bindingCache = Object.create(null);
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
*
|
|
155
|
-
* @param {import("../scope/scope.js").Scope} scope
|
|
156
|
-
* @param {string} directiveName
|
|
157
|
-
* @param {boolean} isController
|
|
158
|
-
* @returns {Object} a configuration object for attribute bindings
|
|
159
|
-
*/
|
|
160
|
-
function parseIsolateBindings(scope, directiveName, isController) {
|
|
161
|
-
const LOCAL_REGEXP = /^([@&]|[=<]())(\??)\s*([\w$]*)$/;
|
|
162
|
-
|
|
163
|
-
const bindings = Object.create(null);
|
|
164
|
-
|
|
165
|
-
Object.entries(scope).forEach(([scopeName, definition]) => {
|
|
166
|
-
definition = definition.trim();
|
|
167
|
-
|
|
168
|
-
if (definition in bindingCache) {
|
|
169
|
-
bindings[scopeName] = bindingCache[definition];
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
const match = definition.match(LOCAL_REGEXP);
|
|
173
|
-
|
|
174
|
-
if (!match) {
|
|
175
|
-
throw $compileMinErr(
|
|
176
|
-
"iscp",
|
|
177
|
-
"Invalid {3} for directive '{0}'." +
|
|
178
|
-
" Definition: {... {1}: '{2}' ...}",
|
|
179
|
-
directiveName,
|
|
180
|
-
scopeName,
|
|
181
|
-
definition,
|
|
182
|
-
isController
|
|
183
|
-
? "controller bindings definition"
|
|
184
|
-
: "isolate scope definition",
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
bindings[scopeName] = {
|
|
189
|
-
mode: match[1][0],
|
|
190
|
-
collection: match[2] === "*",
|
|
191
|
-
optional: match[3] === "?",
|
|
192
|
-
attrName: match[4] || scopeName,
|
|
193
|
-
};
|
|
194
|
-
if (match[4]) {
|
|
195
|
-
bindingCache[definition] = bindings[scopeName];
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
return bindings;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
function parseDirectiveBindings(directive, directiveName) {
|
|
203
|
-
const bindings = {
|
|
204
|
-
isolateScope: null,
|
|
205
|
-
bindToController: null,
|
|
206
|
-
};
|
|
207
|
-
if (isObject(directive.scope)) {
|
|
208
|
-
if (directive.bindToController === true) {
|
|
209
|
-
bindings.bindToController = parseIsolateBindings(
|
|
210
|
-
directive.scope,
|
|
211
|
-
directiveName,
|
|
212
|
-
true,
|
|
213
|
-
);
|
|
214
|
-
bindings.isolateScope = {};
|
|
215
|
-
} else {
|
|
216
|
-
bindings.isolateScope = parseIsolateBindings(
|
|
217
|
-
directive.scope,
|
|
218
|
-
directiveName,
|
|
219
|
-
false,
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
if (isObject(directive.bindToController)) {
|
|
224
|
-
bindings.bindToController = parseIsolateBindings(
|
|
225
|
-
directive.bindToController,
|
|
226
|
-
directiveName,
|
|
227
|
-
true,
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
if (bindings.bindToController && !directive.controller) {
|
|
231
|
-
// There is no controller
|
|
232
|
-
throw $compileMinErr(
|
|
233
|
-
"noctrl",
|
|
234
|
-
"Cannot bind to controller without directive '{0}'s controller.",
|
|
235
|
-
directiveName,
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
return bindings;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function getDirectiveRequire(directive) {
|
|
242
|
-
const require =
|
|
243
|
-
directive.require || (directive.controller && directive.name);
|
|
244
|
-
|
|
245
|
-
if (!Array.isArray(require) && isObject(require)) {
|
|
246
|
-
Object.entries(require).forEach(([key, value]) => {
|
|
247
|
-
const match = value.match(REQUIRE_PREFIX_REGEXP);
|
|
248
|
-
const name = value.substring(match[0].length);
|
|
249
|
-
if (!name) {
|
|
250
|
-
require[key] = match[0] + key;
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
return require;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function getDirectiveRestrict(restrict, name) {
|
|
259
|
-
if (restrict && !(isString(restrict) && /[EA]/.test(restrict))) {
|
|
260
|
-
throw $compileMinErr(
|
|
261
|
-
"badrestrict",
|
|
262
|
-
"Restrict property '{0}' of directive '{1}' is invalid",
|
|
263
|
-
restrict,
|
|
264
|
-
name,
|
|
265
|
-
);
|
|
266
|
-
}
|
|
267
|
-
// Default is element or attribute
|
|
268
|
-
return restrict || "EA";
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Register a new directive with the compiler.
|
|
273
|
-
*
|
|
274
|
-
* @param {string|Object} name Name of the directive in camel-case (i.e. `ngBind` which will match
|
|
275
|
-
* as `ng-bind`), or an object map of directives where the keys are the names and the values
|
|
276
|
-
* are the factories.
|
|
277
|
-
* @param {Function|Array} directiveFactory An injectable directive factory function. See the
|
|
278
|
-
* {@link guide/directive directive guide} and the {@link $compile compile API} for more info.
|
|
279
|
-
* @returns {CompileProvider} Self for chaining.
|
|
280
|
-
*/
|
|
281
|
-
this.directive = function registerDirective(name, directiveFactory) {
|
|
282
|
-
assertArg(name, "name");
|
|
283
|
-
assertNotHasOwnProperty(name, "directive");
|
|
284
|
-
if (isString(name)) {
|
|
285
|
-
assertValidDirectiveName(name);
|
|
286
|
-
assertArg(directiveFactory, "directiveFactory");
|
|
287
|
-
if (!hasOwn(hasDirectives, name)) {
|
|
288
|
-
hasDirectives[name] = [];
|
|
289
|
-
$provide.factory(name + DirectiveSuffix, [
|
|
290
|
-
"$injector",
|
|
291
|
-
"$exceptionHandler",
|
|
292
|
-
/**
|
|
293
|
-
* @param {import("../../core/di/internal-injector.js").InjectorService} $injector
|
|
294
|
-
* @param {import('../../services/exception/exception-handler.js').ErrorHandler} $exceptionHandler
|
|
295
|
-
*/
|
|
296
|
-
function ($injector, $exceptionHandler) {
|
|
297
|
-
const directives = [];
|
|
298
|
-
hasDirectives[name].forEach((directiveFactory, index) => {
|
|
299
|
-
try {
|
|
300
|
-
let directive = $injector.invoke(directiveFactory);
|
|
301
|
-
const valueFn = (value) => () => value;
|
|
302
|
-
if (isFunction(directive)) {
|
|
303
|
-
directive = { compile: valueFn(directive) };
|
|
304
|
-
} else if (!directive.compile && directive.link) {
|
|
305
|
-
directive.compile = valueFn(directive.link);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
directive.priority = directive.priority || 0;
|
|
309
|
-
directive.index = index;
|
|
310
|
-
directive.name = directive.name || name;
|
|
311
|
-
directive.require = getDirectiveRequire(directive);
|
|
312
|
-
directive.restrict = getDirectiveRestrict(
|
|
313
|
-
directive.restrict,
|
|
314
|
-
name,
|
|
315
|
-
);
|
|
316
|
-
directive.$$moduleName = directiveFactory.$$moduleName;
|
|
317
|
-
directives.push(directive);
|
|
318
|
-
} catch (e) {
|
|
319
|
-
$exceptionHandler(e);
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
return directives;
|
|
323
|
-
},
|
|
324
|
-
]);
|
|
325
|
-
}
|
|
326
|
-
hasDirectives[name].push(directiveFactory);
|
|
327
|
-
} else {
|
|
328
|
-
Object.entries(name).forEach(([k, v]) => registerDirective(k, v));
|
|
329
|
-
}
|
|
330
|
-
return this;
|
|
331
|
-
};
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* @param {string|Object} name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`),
|
|
335
|
-
* or an object map of components where the keys are the names and the values are the component definition objects.
|
|
336
|
-
* @param {import("../../interface.js").ComponentOptions} options Component definition object (a simplified
|
|
337
|
-
* {directive definition object}),
|
|
338
|
-
* with the following properties (all optional):
|
|
339
|
-
*
|
|
340
|
-
* - `controller` – `{(string|function()=}` – controller constructor function that should be
|
|
341
|
-
* associated with newly created scope or the name of a {controller} if passed as a string. An empty `noop` function by default.
|
|
342
|
-
* - `controllerAs` – `{string=}` – identifier name for to reference the controller in the component's scope.
|
|
343
|
-
* If present, the controller will be published to scope under the `controllerAs` name.
|
|
344
|
-
* If not present, this will default to be `$ctrl`.
|
|
345
|
-
* - `template` – `{string=|function()=}` – html template as a string or a function that
|
|
346
|
-
* returns an html template as a string which should be used as the contents of this component.
|
|
347
|
-
* Empty string by default.
|
|
348
|
-
*
|
|
349
|
-
* If `template` is a function, then it is {injected} with
|
|
350
|
-
* the following locals:
|
|
351
|
-
*
|
|
352
|
-
* - `$element` - Current element
|
|
353
|
-
* - `$attrs` - Current attributes object for the element
|
|
354
|
-
*
|
|
355
|
-
* - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
|
|
356
|
-
* template that should be used as the contents of this component.
|
|
357
|
-
*
|
|
358
|
-
* If `templateUrl` is a function, then it is {injected} with
|
|
359
|
-
* the following locals:
|
|
360
|
-
*
|
|
361
|
-
* - `$element` - Current element
|
|
362
|
-
* - `$attrs` - Current attributes object for the element
|
|
363
|
-
*
|
|
364
|
-
* - `bindings` – `{object=}` – defines bindings between DOM attributes and component properties.
|
|
365
|
-
* Component properties are always bound to the component controller and not to the scope.
|
|
366
|
-
* See {`bindToController`}.
|
|
367
|
-
* - `transclude` – `{boolean=}` – whether {content transclusion} is enabled.
|
|
368
|
-
* Disabled by default.
|
|
369
|
-
* - `require` - `{Object<string, string>=}` - requires the controllers of other directives and binds them to
|
|
370
|
-
* this component's controller. The object keys specify the property names under which the required
|
|
371
|
-
* controllers (object values) will be bound. See {`require`}.
|
|
372
|
-
* - `$...` – additional properties to attach to the directive factory function and the controller
|
|
373
|
-
* constructor function. (This is used by the component router to annotate)
|
|
374
|
-
*
|
|
375
|
-
* @returns {CompileProvider} the compile provider itself, for chaining of function calls.
|
|
376
|
-
*/
|
|
377
|
-
this.component = function (name, options) {
|
|
378
|
-
if (!isString(name)) {
|
|
379
|
-
Object.entries(name).forEach(([key, val]) => this.component(key, val));
|
|
380
|
-
return this;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
const controller = options.controller || function () {};
|
|
384
|
-
|
|
385
|
-
function factory($injector) {
|
|
386
|
-
function makeInjectable(fn) {
|
|
387
|
-
if (isFunction(fn) || Array.isArray(fn)) {
|
|
388
|
-
return function (tElement, tAttrs) {
|
|
389
|
-
return $injector.invoke(fn, this, {
|
|
390
|
-
$element: tElement,
|
|
391
|
-
$attrs: tAttrs,
|
|
392
|
-
});
|
|
393
|
-
};
|
|
394
|
-
}
|
|
395
|
-
return fn;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
const template =
|
|
399
|
-
!options.template && !options.templateUrl ? "" : options.template;
|
|
400
|
-
const ddo = {
|
|
401
|
-
controller,
|
|
402
|
-
controllerAs:
|
|
403
|
-
identifierForController(options.controller) ||
|
|
404
|
-
options.controllerAs ||
|
|
405
|
-
"$ctrl",
|
|
406
|
-
template: makeInjectable(template),
|
|
407
|
-
templateUrl: makeInjectable(options.templateUrl),
|
|
408
|
-
transclude: options.transclude,
|
|
409
|
-
scope: {},
|
|
410
|
-
bindToController: options.bindings || {},
|
|
411
|
-
restrict: "E",
|
|
412
|
-
require: options.require,
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
// Copy annotations (starting with $) over to the DDO
|
|
416
|
-
Object.entries(options).forEach(([key, val]) => {
|
|
417
|
-
if (key.charAt(0) === "$") {
|
|
418
|
-
ddo[key] = val;
|
|
419
|
-
}
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
return ddo;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// Copy any annotation properties (starting with $) over to the factory and controller constructor functions
|
|
426
|
-
// These could be used by libraries such as the new component router
|
|
427
|
-
Object.entries(options).forEach(([key, val]) => {
|
|
428
|
-
if (key.charAt(0) === "$") {
|
|
429
|
-
factory[key] = val;
|
|
430
|
-
// Don't try to copy over annotations to named controller
|
|
431
|
-
if (isFunction(controller)) {
|
|
432
|
-
controller[key] = val;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
factory.$inject = ["$injector"];
|
|
438
|
-
|
|
439
|
-
return this.directive(name, factory);
|
|
440
|
-
};
|
|
441
|
-
|
|
442
|
-
/**
|
|
443
|
-
* Retrieves or overrides the default regular expression that is used for determining trusted safe
|
|
444
|
-
* urls during a[href] sanitization.
|
|
445
|
-
*
|
|
446
|
-
* The sanitization is a security measure aimed at preventing XSS attacks via html links.
|
|
447
|
-
*
|
|
448
|
-
* Any url about to be assigned to a[href] via data-binding is first normalized and turned into
|
|
449
|
-
* an absolute url. Afterwards, the url is matched against the `aHrefSanitizationTrustedUrlList`
|
|
450
|
-
* regular expression. If a match is found, the original url is written into the dom. Otherwise,
|
|
451
|
-
* the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
|
|
452
|
-
*
|
|
453
|
-
* @param {RegExp=} regexp New regexp to trust urls with.
|
|
454
|
-
* @returns {RegExp|import('../sanitize/sanitize-uri.js').SanitizeUriProvider} Current RegExp if called without value or self for
|
|
455
|
-
* chaining otherwise.
|
|
456
|
-
*/
|
|
457
|
-
this.aHrefSanitizationTrustedUrlList = function (regexp) {
|
|
458
|
-
if (isDefined(regexp)) {
|
|
459
|
-
$$sanitizeUriProvider.aHrefSanitizationTrustedUrlList(regexp);
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
|
-
return $$sanitizeUriProvider.aHrefSanitizationTrustedUrlList();
|
|
463
|
-
};
|
|
464
|
-
|
|
465
|
-
/**
|
|
466
|
-
* Retrieves or overrides the default regular expression that is used for determining trusted safe
|
|
467
|
-
* urls during img[src] sanitization.
|
|
468
|
-
*
|
|
469
|
-
* The sanitization is a security measure aimed at prevent XSS attacks via html links.
|
|
470
|
-
*
|
|
471
|
-
* Any url about to be assigned to img[src] via data-binding is first normalized and turned into
|
|
472
|
-
* an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationTrustedUrlList`
|
|
473
|
-
* regular expression. If a match is found, the original url is written into the dom. Otherwise,
|
|
474
|
-
* the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
|
|
475
|
-
*
|
|
476
|
-
* @param {RegExp=} regexp New regexp to trust urls with.
|
|
477
|
-
* @returns {RegExp|import('../sanitize/sanitize-uri.js').SanitizeUriProvider} Current RegExp if called without value or self for
|
|
478
|
-
* chaining otherwise.
|
|
479
|
-
*/
|
|
480
|
-
this.imgSrcSanitizationTrustedUrlList = function (regexp) {
|
|
481
|
-
if (isDefined(regexp)) {
|
|
482
|
-
$$sanitizeUriProvider.imgSrcSanitizationTrustedUrlList(regexp);
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
return $$sanitizeUriProvider.imgSrcSanitizationTrustedUrlList();
|
|
486
|
-
};
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* @param {boolean=} enabled update the strictComponentBindingsEnabled state if provided,
|
|
490
|
-
* otherwise return the current strictComponentBindingsEnabled state.
|
|
491
|
-
* @returns {*} current value if used as getter or itself (chaining) if used as setter
|
|
492
|
-
*
|
|
493
|
-
* Call this method to enable / disable the strict component bindings check. If enabled, the
|
|
494
|
-
* compiler will enforce that all scope / controller bindings of a
|
|
495
|
-
* {@link $compileProvider#directive directive} / {@link $compileProvider#component component}
|
|
496
|
-
* that are not set as optional with `?`, must be provided when the directive is instantiated.
|
|
497
|
-
* If not provided, the compiler will throw the
|
|
498
|
-
* {@link error/$compile/missingattr $compile:missingattr error}.
|
|
499
|
-
*
|
|
500
|
-
* The default value is false.
|
|
501
|
-
*/
|
|
502
|
-
let strictComponentBindingsEnabled = false;
|
|
503
|
-
this.strictComponentBindingsEnabled = function (enabled) {
|
|
504
|
-
if (isDefined(enabled)) {
|
|
505
|
-
strictComponentBindingsEnabled = enabled;
|
|
506
|
-
return this;
|
|
507
|
-
}
|
|
508
|
-
return strictComponentBindingsEnabled;
|
|
509
|
-
};
|
|
510
|
-
|
|
511
|
-
/**
|
|
512
|
-
* The security context of DOM Properties.
|
|
513
|
-
*/
|
|
514
|
-
const PROP_CONTEXTS = Object.create(null);
|
|
515
|
-
|
|
516
|
-
/**
|
|
517
|
-
* Defines the security context for DOM properties bound by ng-prop-*.
|
|
518
|
-
*
|
|
519
|
-
* @param {string} elementName The element name or '*' to match any element.
|
|
520
|
-
* @param {string} propertyName The DOM property name.
|
|
521
|
-
* @param {string} ctx The {@link $sce} security context in which this value is safe for use, e.g. `$sce.URL`
|
|
522
|
-
* @returns {object} `this` for chaining
|
|
523
|
-
*/
|
|
524
|
-
this.addPropertySecurityContext = function (
|
|
525
|
-
elementName,
|
|
526
|
-
propertyName,
|
|
527
|
-
ctx,
|
|
528
|
-
) {
|
|
529
|
-
const key = `${elementName.toLowerCase()}|${propertyName.toLowerCase()}`;
|
|
530
|
-
|
|
531
|
-
if (key in PROP_CONTEXTS && PROP_CONTEXTS[key] !== ctx) {
|
|
532
|
-
throw $compileMinErr(
|
|
533
|
-
"ctxoverride",
|
|
534
|
-
"Property context '{0}.{1}' already set to '{2}', cannot override to '{3}'.",
|
|
535
|
-
elementName,
|
|
536
|
-
propertyName,
|
|
537
|
-
PROP_CONTEXTS[key],
|
|
538
|
-
ctx,
|
|
539
|
-
);
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
PROP_CONTEXTS[key] = ctx;
|
|
543
|
-
return this;
|
|
544
|
-
};
|
|
545
|
-
|
|
546
|
-
/* Default property contexts.
|
|
547
|
-
*
|
|
548
|
-
* Copy of https://github.com/angular/angular/blob/6.0.6/packages/compiler/src/schema/dom_security_schema.ts#L31-L58
|
|
549
|
-
* Changing:
|
|
550
|
-
* - SecurityContext.* => SCE_CONTEXTS/$sce.*
|
|
551
|
-
* - STYLE => CSS
|
|
552
|
-
* - various URL => MEDIA_URL
|
|
553
|
-
* - *|formAction, form|action URL => RESOURCE_URL (like the attribute)
|
|
554
|
-
*/
|
|
555
|
-
(function registerNativePropertyContexts() {
|
|
556
|
-
function registerContext(ctx, values) {
|
|
557
|
-
values.forEach((v) => {
|
|
558
|
-
PROP_CONTEXTS[v.toLowerCase()] = ctx;
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
registerContext(SCE_CONTEXTS.HTML, [
|
|
563
|
-
"iframe|srcdoc",
|
|
564
|
-
"*|innerHTML",
|
|
565
|
-
"*|outerHTML",
|
|
566
|
-
]);
|
|
567
|
-
registerContext(SCE_CONTEXTS.CSS, ["*|style"]);
|
|
568
|
-
registerContext(SCE_CONTEXTS.URL, [
|
|
569
|
-
"area|href",
|
|
570
|
-
"area|ping",
|
|
571
|
-
"a|href",
|
|
572
|
-
"a|ping",
|
|
573
|
-
"blockquote|cite",
|
|
574
|
-
"body|background",
|
|
575
|
-
"del|cite",
|
|
576
|
-
"input|src",
|
|
577
|
-
"ins|cite",
|
|
578
|
-
"q|cite",
|
|
579
|
-
]);
|
|
580
|
-
registerContext(SCE_CONTEXTS.MEDIA_URL, [
|
|
581
|
-
"audio|src",
|
|
582
|
-
"img|src",
|
|
583
|
-
"img|srcset",
|
|
584
|
-
"source|src",
|
|
585
|
-
"source|srcset",
|
|
586
|
-
"track|src",
|
|
587
|
-
"video|src",
|
|
588
|
-
"video|poster",
|
|
589
|
-
]);
|
|
590
|
-
registerContext(SCE_CONTEXTS.RESOURCE_URL, [
|
|
591
|
-
"*|formAction",
|
|
592
|
-
"applet|code",
|
|
593
|
-
"applet|codebase",
|
|
594
|
-
"base|href",
|
|
595
|
-
"embed|src",
|
|
596
|
-
"frame|src",
|
|
597
|
-
"form|action",
|
|
598
|
-
"head|profile",
|
|
599
|
-
"html|manifest",
|
|
600
|
-
"iframe|src",
|
|
601
|
-
"link|href",
|
|
602
|
-
"media|src",
|
|
603
|
-
"object|codebase",
|
|
604
|
-
"object|data",
|
|
605
|
-
"script|src",
|
|
606
|
-
]);
|
|
607
|
-
})();
|
|
608
|
-
|
|
609
|
-
this.$get = [
|
|
610
|
-
"$injector",
|
|
611
|
-
"$interpolate",
|
|
612
|
-
"$exceptionHandler",
|
|
613
|
-
"$templateRequest",
|
|
614
|
-
"$parse",
|
|
615
|
-
"$controller",
|
|
616
|
-
"$rootScope",
|
|
617
|
-
"$sce",
|
|
618
|
-
"$animate",
|
|
619
|
-
/**
|
|
620
|
-
* @param {import("../../core/di/internal-injector.js").InjectorService} $injector
|
|
621
|
-
* @param {*} $interpolate
|
|
622
|
-
* @param {import("../../services/exception/exception-handler.js").ErrorHandler} $exceptionHandler
|
|
623
|
-
* @param {*} $templateRequest
|
|
624
|
-
* @param {import("../parse/interface.ts").ParseService} $parse
|
|
625
|
-
* @param {*} $controller
|
|
626
|
-
* @param {import('../scope/scope.js').Scope} $rootScope
|
|
627
|
-
* @param {*} $sce
|
|
628
|
-
* @param {*} $animate
|
|
629
|
-
* @returns
|
|
630
|
-
*/
|
|
631
|
-
function (
|
|
632
|
-
$injector,
|
|
633
|
-
$interpolate,
|
|
634
|
-
$exceptionHandler,
|
|
635
|
-
$templateRequest,
|
|
636
|
-
$parse,
|
|
637
|
-
$controller,
|
|
638
|
-
$rootScope,
|
|
639
|
-
$sce,
|
|
640
|
-
$animate,
|
|
641
|
-
) {
|
|
642
|
-
// The onChanges hooks should all be run together in a single digest
|
|
643
|
-
// When changes occur, the call to trigger their hooks will be added to this queue
|
|
644
|
-
let onChangesQueue;
|
|
645
|
-
|
|
646
|
-
// This function is called in a $postUpdate to trigger all the onChanges hooks in a single digest
|
|
647
|
-
function flushOnChangesQueue() {
|
|
648
|
-
for (let i = 0, ii = onChangesQueue.length; i < ii; ++i) {
|
|
649
|
-
try {
|
|
650
|
-
onChangesQueue[i]();
|
|
651
|
-
} catch (e) {
|
|
652
|
-
$exceptionHandler(e);
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
// Reset the queue to trigger a new schedule next time there is a change
|
|
656
|
-
onChangesQueue = undefined;
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
const startSymbol = $interpolate.startSymbol();
|
|
660
|
-
const endSymbol = $interpolate.endSymbol();
|
|
661
|
-
/** @type {(string) => string} */
|
|
662
|
-
const denormalizeTemplate =
|
|
663
|
-
startSymbol === "{{" && endSymbol === "}}"
|
|
664
|
-
? (x) => x
|
|
665
|
-
: (x) => x.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
|
|
666
|
-
|
|
667
|
-
const NG_PREFIX_BINDING = /^ng(Attr|Prop|On|Observe)([A-Z].*)$/;
|
|
668
|
-
return compile;
|
|
669
|
-
|
|
670
|
-
//= ===============================
|
|
671
|
-
/**
|
|
672
|
-
* @type {CompileFn}
|
|
673
|
-
*/
|
|
674
|
-
function compile(
|
|
675
|
-
element,
|
|
676
|
-
transcludeFn,
|
|
677
|
-
maxPriority,
|
|
678
|
-
ignoreDirective,
|
|
679
|
-
previousCompileContext,
|
|
680
|
-
) {
|
|
681
|
-
/** @type {NodeRef | null } */
|
|
682
|
-
let nodeRef = new NodeRef(element);
|
|
683
|
-
/**
|
|
684
|
-
* The composite link function is a composite of individual node linking functions.
|
|
685
|
-
* It will be invoke by the public link function below.
|
|
686
|
-
* @type {CompositeLinkFn}
|
|
687
|
-
*/
|
|
688
|
-
let compositeLinkFn = compileNodes(
|
|
689
|
-
nodeRef,
|
|
690
|
-
transcludeFn,
|
|
691
|
-
maxPriority,
|
|
692
|
-
ignoreDirective,
|
|
693
|
-
previousCompileContext,
|
|
694
|
-
);
|
|
695
|
-
|
|
696
|
-
let namespace = null;
|
|
697
|
-
return publicLinkFn;
|
|
698
|
-
|
|
699
|
-
/** @type {PublicLinkFn} */
|
|
700
|
-
function publicLinkFn(scope, cloneConnectFn, options) {
|
|
701
|
-
if (!nodeRef) {
|
|
702
|
-
throw $compileMinErr(
|
|
703
|
-
"multilink",
|
|
704
|
-
"This element has already been linked.",
|
|
705
|
-
);
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
assertArg(scope, "scope");
|
|
709
|
-
// could be empty nodelist
|
|
710
|
-
if (nodeRef.getAny()) {
|
|
711
|
-
setScope(nodeRef.getAny(), scope);
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
if (
|
|
715
|
-
previousCompileContext &&
|
|
716
|
-
previousCompileContext.needsNewScope
|
|
717
|
-
) {
|
|
718
|
-
// A parent directive did a replace and a directive on this element asked
|
|
719
|
-
// for transclusion, which caused us to lose a layer of element on which
|
|
720
|
-
// we could hold the new transclusion scope, so we will create it manually
|
|
721
|
-
// here.
|
|
722
|
-
scope = scope.$parent.$new();
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
options = options || {};
|
|
726
|
-
let {
|
|
727
|
-
transcludeControllers,
|
|
728
|
-
parentBoundTranscludeFn,
|
|
729
|
-
futureParentElement,
|
|
730
|
-
} = options;
|
|
731
|
-
|
|
732
|
-
// When `parentBoundTranscludeFn` is passed, it is a
|
|
733
|
-
// `controllersBoundTransclude` function (it was previously passed
|
|
734
|
-
// as `transclude` to directive.link) so we must unwrap it to get
|
|
735
|
-
// its `boundTranscludeFn`
|
|
736
|
-
if (
|
|
737
|
-
parentBoundTranscludeFn &&
|
|
738
|
-
parentBoundTranscludeFn.$$boundTransclude
|
|
739
|
-
) {
|
|
740
|
-
parentBoundTranscludeFn =
|
|
741
|
-
parentBoundTranscludeFn.$$boundTransclude;
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
if (!namespace) {
|
|
745
|
-
namespace = detectNamespaceForChildElements(futureParentElement);
|
|
746
|
-
}
|
|
747
|
-
/** @type {NodeRef} */
|
|
748
|
-
let $linkNode;
|
|
749
|
-
|
|
750
|
-
if (namespace !== "html") {
|
|
751
|
-
// When using a directive with replace:true and templateUrl the jqCompileNodes
|
|
752
|
-
// (or a child element inside of them)
|
|
753
|
-
// might change, so we need to recreate the namespace adapted compileNodes
|
|
754
|
-
// for call to the link function.
|
|
755
|
-
// Note: This will already clone the nodes...
|
|
756
|
-
const fragment = createElementFromHTML("<div></div>");
|
|
757
|
-
fragment.append(nodeRef.node);
|
|
758
|
-
const wrappedTemplate = wrapTemplate(
|
|
759
|
-
namespace,
|
|
760
|
-
fragment.innerHTML,
|
|
761
|
-
);
|
|
762
|
-
$linkNode = new NodeRef(wrappedTemplate[0]);
|
|
763
|
-
} else if (cloneConnectFn) {
|
|
764
|
-
$linkNode = nodeRef.clone();
|
|
765
|
-
} else {
|
|
766
|
-
$linkNode = nodeRef;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
if (transcludeControllers) {
|
|
770
|
-
for (const controllerName in transcludeControllers) {
|
|
771
|
-
assertArg($linkNode.element, "element");
|
|
772
|
-
setCacheData(
|
|
773
|
-
$linkNode.element,
|
|
774
|
-
`$${controllerName}Controller`,
|
|
775
|
-
transcludeControllers[controllerName].instance,
|
|
776
|
-
);
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
if (cloneConnectFn) {
|
|
780
|
-
cloneConnectFn($linkNode.dom, scope);
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
if (compositeLinkFn) {
|
|
784
|
-
compositeLinkFn(scope, $linkNode, parentBoundTranscludeFn);
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
if (!cloneConnectFn) {
|
|
788
|
-
nodeRef = compositeLinkFn = null;
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
$linkNode.linked = true;
|
|
792
|
-
|
|
793
|
-
return $linkNode.getAll();
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
function detectNamespaceForChildElements(parentElement) {
|
|
798
|
-
// TODO: Make this detect MathML as well...
|
|
799
|
-
const node = parentElement;
|
|
800
|
-
if (!node) {
|
|
801
|
-
return "html";
|
|
802
|
-
}
|
|
803
|
-
return getNodeName(node) !== "foreignobject" &&
|
|
804
|
-
toString.call(node).match(/SVG/)
|
|
805
|
-
? "svg"
|
|
806
|
-
: "html";
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
/**
|
|
810
|
-
* Compile function matches each node in nodeList against the directives. Once all directives
|
|
811
|
-
* for a particular node are collected their compile functions are executed. The compile
|
|
812
|
-
* functions return values - the linking functions - are combined into a composite linking
|
|
813
|
-
* function, which is a linking function for the node.
|
|
814
|
-
*
|
|
815
|
-
* @param {NodeRef} nodeRefList a node or an array of nodes or NodeList to compile
|
|
816
|
-
* @param {*} transcludeFn A linking function, where the
|
|
817
|
-
* scope argument is auto-generated to the new child of the transcluded parent scope.
|
|
818
|
-
* @param {number=} [maxPriority] Max directive priority.
|
|
819
|
-
* @param {*} [ignoreDirective]
|
|
820
|
-
* @param {*} [previousCompileContext]
|
|
821
|
-
* @returns {CompositeLinkFn} A composite linking function of all of the matched directives or null.
|
|
822
|
-
*/
|
|
823
|
-
function compileNodes(
|
|
824
|
-
nodeRefList,
|
|
825
|
-
transcludeFn,
|
|
826
|
-
maxPriority,
|
|
827
|
-
ignoreDirective,
|
|
828
|
-
previousCompileContext,
|
|
829
|
-
) {
|
|
830
|
-
/**
|
|
831
|
-
* Aggregates for the composite linking function, where a node in a node list is mapped
|
|
832
|
-
* to a corresponding link function. For single elements, the node should be mapped to
|
|
833
|
-
* a single node link function.
|
|
834
|
-
* @type {LinkFnMapping[]}
|
|
835
|
-
*/
|
|
836
|
-
const linkFnsList = []; // An array to hold node indices and their linkFns
|
|
837
|
-
let nodeLinkFnFound;
|
|
838
|
-
let linkFnFound = false;
|
|
839
|
-
for (let i = 0; i < nodeRefList.size; i++) {
|
|
840
|
-
const attrs = new Attributes(
|
|
841
|
-
$rootScope,
|
|
842
|
-
$animate,
|
|
843
|
-
$exceptionHandler,
|
|
844
|
-
$sce,
|
|
845
|
-
);
|
|
846
|
-
|
|
847
|
-
const directives = collectDirectives(
|
|
848
|
-
/** @type Element */ (nodeRefList.getIndex(i)),
|
|
849
|
-
attrs,
|
|
850
|
-
i === 0 ? maxPriority : undefined,
|
|
851
|
-
ignoreDirective,
|
|
852
|
-
);
|
|
853
|
-
|
|
854
|
-
/** @type {NodeLinkFnCtx} */
|
|
855
|
-
let nodeLinkFnCtx;
|
|
856
|
-
|
|
857
|
-
if (directives.length) {
|
|
858
|
-
nodeLinkFnCtx = applyDirectivesToNode(
|
|
859
|
-
directives,
|
|
860
|
-
nodeRefList.getIndex(i),
|
|
861
|
-
attrs,
|
|
862
|
-
transcludeFn,
|
|
863
|
-
null,
|
|
864
|
-
[],
|
|
865
|
-
[],
|
|
866
|
-
Object.assign({}, previousCompileContext, {
|
|
867
|
-
index: i,
|
|
868
|
-
parentNodeRef: nodeRefList,
|
|
869
|
-
ctxNodeRef: nodeRefList,
|
|
870
|
-
}),
|
|
871
|
-
);
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
let childLinkFn;
|
|
875
|
-
let childNodes;
|
|
876
|
-
let nodeLinkFn = nodeLinkFnCtx?.nodeLinkFn;
|
|
877
|
-
if (
|
|
878
|
-
(nodeLinkFn && nodeLinkFnCtx.terminal) ||
|
|
879
|
-
!(childNodes = nodeRefList.getIndex(i).childNodes) ||
|
|
880
|
-
!childNodes.length
|
|
881
|
-
) {
|
|
882
|
-
childLinkFn = null;
|
|
883
|
-
} else {
|
|
884
|
-
let transcluded = nodeLinkFn
|
|
885
|
-
? (nodeLinkFnCtx.transcludeOnThisElement ||
|
|
886
|
-
!nodeLinkFnCtx.templateOnThisElement) &&
|
|
887
|
-
nodeLinkFnCtx.transclude
|
|
888
|
-
: transcludeFn;
|
|
889
|
-
// recursive call
|
|
890
|
-
const childNodeRef = new NodeRef(childNodes);
|
|
891
|
-
childLinkFn = compileNodes(childNodeRef, transcluded);
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
if (nodeLinkFn || childLinkFn) {
|
|
895
|
-
linkFnsList.push({
|
|
896
|
-
index: i,
|
|
897
|
-
nodeLinkFnCtx: nodeLinkFnCtx,
|
|
898
|
-
childLinkFn: childLinkFn,
|
|
899
|
-
});
|
|
900
|
-
linkFnFound = true;
|
|
901
|
-
nodeLinkFnFound = nodeLinkFnFound || nodeLinkFn;
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
// use the previous context only for the first element in the virtual group
|
|
905
|
-
previousCompileContext = null;
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
// return a composite linking function if we have found anything, null otherwise
|
|
909
|
-
return linkFnFound ? compositeLinkFn : null;
|
|
910
|
-
|
|
911
|
-
/**
|
|
912
|
-
* The composite link function links all the individual nodes
|
|
913
|
-
*
|
|
914
|
-
* @param {import("../scope/scope.js").Scope} scope
|
|
915
|
-
* @param {NodeRef} nodeRef
|
|
916
|
-
* @param {*} [parentBoundTranscludeFn]
|
|
917
|
-
*/
|
|
918
|
-
function compositeLinkFn(scope, nodeRef, parentBoundTranscludeFn) {
|
|
919
|
-
assertArg(nodeRef, "nodeRef");
|
|
920
|
-
let stableNodeList = [];
|
|
921
|
-
if (nodeLinkFnFound) {
|
|
922
|
-
// create a stable copy of the nodeList, only copying elements with linkFns
|
|
923
|
-
const stableLength = nodeRef.isList ? nodeRef.nodes.length : 1;
|
|
924
|
-
stableNodeList = new Array(stableLength);
|
|
925
|
-
// create a sparse array by only copying the elements which have a linkFn
|
|
926
|
-
linkFnsList.forEach((val) => {
|
|
927
|
-
let idx = val.index;
|
|
928
|
-
if (idx === 0) {
|
|
929
|
-
stableNodeList[idx] = nodeRef.isList
|
|
930
|
-
? nodeRef.nodes[idx]
|
|
931
|
-
: nodeRef.node;
|
|
932
|
-
} else {
|
|
933
|
-
if (nodeRefList.getIndex(idx)) {
|
|
934
|
-
stableNodeList[idx] = nodeRef.nodes[idx];
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
});
|
|
938
|
-
} else {
|
|
939
|
-
if (nodeRef.isList) {
|
|
940
|
-
nodeRef.nodes.forEach((elem) => stableNodeList.push(elem));
|
|
941
|
-
} else {
|
|
942
|
-
stableNodeList.push(nodeRef.node);
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
linkFnsList.forEach(({ index, nodeLinkFnCtx, childLinkFn }) => {
|
|
947
|
-
const node = stableNodeList[index];
|
|
948
|
-
node.stable = true;
|
|
949
|
-
let childScope;
|
|
950
|
-
let childBoundTranscludeFn;
|
|
951
|
-
|
|
952
|
-
if (nodeLinkFnCtx?.nodeLinkFn) {
|
|
953
|
-
childScope = nodeLinkFnCtx.newScope ? scope.$new() : scope;
|
|
954
|
-
|
|
955
|
-
if (nodeLinkFnCtx.transcludeOnThisElement) {
|
|
956
|
-
// bind proper scope for the translusion function
|
|
957
|
-
childBoundTranscludeFn = createBoundTranscludeFn(
|
|
958
|
-
scope,
|
|
959
|
-
nodeLinkFnCtx.transclude,
|
|
960
|
-
parentBoundTranscludeFn,
|
|
961
|
-
);
|
|
962
|
-
} else if (
|
|
963
|
-
!nodeLinkFnCtx.templateOnThisElement &&
|
|
964
|
-
parentBoundTranscludeFn
|
|
965
|
-
) {
|
|
966
|
-
childBoundTranscludeFn = parentBoundTranscludeFn;
|
|
967
|
-
} else if (!parentBoundTranscludeFn && transcludeFn) {
|
|
968
|
-
childBoundTranscludeFn = createBoundTranscludeFn(
|
|
969
|
-
scope,
|
|
970
|
-
transcludeFn,
|
|
971
|
-
);
|
|
972
|
-
} else {
|
|
973
|
-
childBoundTranscludeFn = null;
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
// attach new scope to element
|
|
977
|
-
if (nodeLinkFnCtx?.newScope) {
|
|
978
|
-
setScope(node, childScope);
|
|
979
|
-
}
|
|
980
|
-
// @ts-ignore
|
|
981
|
-
nodeLinkFnCtx.nodeLinkFn(
|
|
982
|
-
// @ts-ignore
|
|
983
|
-
childLinkFn,
|
|
984
|
-
childScope,
|
|
985
|
-
node,
|
|
986
|
-
childBoundTranscludeFn,
|
|
987
|
-
);
|
|
988
|
-
} else if (childLinkFn) {
|
|
989
|
-
childLinkFn(
|
|
990
|
-
scope,
|
|
991
|
-
new NodeRef(node.childNodes),
|
|
992
|
-
parentBoundTranscludeFn,
|
|
993
|
-
);
|
|
994
|
-
}
|
|
995
|
-
});
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
/**
|
|
1000
|
-
* Prebinds the transclusion function to a scope
|
|
1001
|
-
* @param {import("../scope/scope.js").Scope} scope
|
|
1002
|
-
* @param {*} transcludeFn
|
|
1003
|
-
* @param {*} previousBoundTranscludeFn
|
|
1004
|
-
* @returns {BoundTranscludeFn}
|
|
1005
|
-
*/
|
|
1006
|
-
function createBoundTranscludeFn(
|
|
1007
|
-
scope,
|
|
1008
|
-
transcludeFn,
|
|
1009
|
-
previousBoundTranscludeFn,
|
|
1010
|
-
) {
|
|
1011
|
-
function boundTranscludeFn(
|
|
1012
|
-
transcludedScope,
|
|
1013
|
-
cloneFn,
|
|
1014
|
-
controllers,
|
|
1015
|
-
futureParentElement,
|
|
1016
|
-
containingScope,
|
|
1017
|
-
) {
|
|
1018
|
-
if (!transcludedScope) {
|
|
1019
|
-
transcludedScope = scope.$transcluded(containingScope);
|
|
1020
|
-
transcludedScope.$$transcluded = true;
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
const transcludeRes = transcludeFn(transcludedScope, cloneFn, {
|
|
1024
|
-
parentBoundTranscludeFn: previousBoundTranscludeFn,
|
|
1025
|
-
transcludeControllers: controllers,
|
|
1026
|
-
futureParentElement,
|
|
1027
|
-
});
|
|
1028
|
-
|
|
1029
|
-
return transcludeRes;
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
// We need to attach the transclusion slots onto the `boundTranscludeFn`
|
|
1033
|
-
// so that they are available inside the `controllersBoundTransclude` function
|
|
1034
|
-
const boundSlots = (boundTranscludeFn.$$slots = Object.create(null));
|
|
1035
|
-
for (const slotName in transcludeFn.$$slots) {
|
|
1036
|
-
if (transcludeFn.$$slots[slotName]) {
|
|
1037
|
-
boundSlots[slotName] = createBoundTranscludeFn(
|
|
1038
|
-
scope,
|
|
1039
|
-
transcludeFn.$$slots[slotName],
|
|
1040
|
-
previousBoundTranscludeFn,
|
|
1041
|
-
);
|
|
1042
|
-
} else {
|
|
1043
|
-
boundSlots[slotName] = null;
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
return boundTranscludeFn;
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
/**
|
|
1051
|
-
* Looks for directives on the given node and adds them to the directive collection which is
|
|
1052
|
-
* sorted.
|
|
1053
|
-
*
|
|
1054
|
-
* @param {Element} node Node to search.
|
|
1055
|
-
* @param {Attributes|any} attrs The shared attrs object which is used to populate the normalized attributes.
|
|
1056
|
-
* @param {number=} maxPriority Max directive priority.
|
|
1057
|
-
* @param {string} [ignoreDirective]
|
|
1058
|
-
* @return {import('../../interface.ts').Directive[]} An array to which the directives are added to. This array is sorted before the function returns.
|
|
1059
|
-
*/
|
|
1060
|
-
function collectDirectives(node, attrs, maxPriority, ignoreDirective) {
|
|
1061
|
-
/**
|
|
1062
|
-
* @type {import('../../interface.ts').Directive[]}
|
|
1063
|
-
*/
|
|
1064
|
-
const directives = [];
|
|
1065
|
-
const { nodeType } = node;
|
|
1066
|
-
const attrsMap = attrs.$attr;
|
|
1067
|
-
let nodeName;
|
|
1068
|
-
|
|
1069
|
-
switch (nodeType) {
|
|
1070
|
-
case Node.ELEMENT_NODE /* Element */:
|
|
1071
|
-
nodeName = node.nodeName.toLowerCase();
|
|
1072
|
-
if (ignoreDirective !== directiveNormalize(nodeName)) {
|
|
1073
|
-
// use the node name: <directive>
|
|
1074
|
-
addDirective(
|
|
1075
|
-
directives,
|
|
1076
|
-
directiveNormalize(nodeName),
|
|
1077
|
-
"E",
|
|
1078
|
-
maxPriority,
|
|
1079
|
-
);
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
// iterate over the attributes
|
|
1083
|
-
for (let j = 0; j < node.attributes?.length; j++) {
|
|
1084
|
-
let isNgAttr = false;
|
|
1085
|
-
let isNgProp = false;
|
|
1086
|
-
let isNgEvent = false;
|
|
1087
|
-
let isNgObserve = false;
|
|
1088
|
-
|
|
1089
|
-
let attr = node.attributes[j];
|
|
1090
|
-
let name = attr.name;
|
|
1091
|
-
let value = attr.value;
|
|
1092
|
-
let nName = directiveNormalize(name.toLowerCase());
|
|
1093
|
-
|
|
1094
|
-
// Support ng-attr-*, ng-prop-* and ng-on-*
|
|
1095
|
-
const ngPrefixMatch = nName.match(NG_PREFIX_BINDING);
|
|
1096
|
-
if (ngPrefixMatch) {
|
|
1097
|
-
isNgAttr = ngPrefixMatch[1] === "Attr";
|
|
1098
|
-
isNgProp = ngPrefixMatch[1] === "Prop";
|
|
1099
|
-
isNgEvent = ngPrefixMatch[1] === "On";
|
|
1100
|
-
isNgObserve = ngPrefixMatch[1] === "Observe";
|
|
1101
|
-
|
|
1102
|
-
// Normalize the non-prefixed name
|
|
1103
|
-
name = name
|
|
1104
|
-
.replace(PREFIX_REGEXP, "")
|
|
1105
|
-
.toLowerCase()
|
|
1106
|
-
.substring(4 + ngPrefixMatch[1].length)
|
|
1107
|
-
.replace(/_(.)/g, (match, letter) => letter.toUpperCase());
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
if (isNgProp || isNgEvent) {
|
|
1111
|
-
attrs[nName] = value;
|
|
1112
|
-
attrsMap[nName] = attr.name;
|
|
1113
|
-
|
|
1114
|
-
if (isNgProp) {
|
|
1115
|
-
addPropertyDirective(node, directives, nName, name);
|
|
1116
|
-
} else {
|
|
1117
|
-
directives.push(
|
|
1118
|
-
createEventDirective(
|
|
1119
|
-
$parse,
|
|
1120
|
-
$exceptionHandler,
|
|
1121
|
-
nName,
|
|
1122
|
-
name,
|
|
1123
|
-
),
|
|
1124
|
-
);
|
|
1125
|
-
}
|
|
1126
|
-
} else if (isNgObserve) {
|
|
1127
|
-
directives.push(ngObserveDirective(name, value));
|
|
1128
|
-
} else {
|
|
1129
|
-
// Update nName for cases where a prefix was removed
|
|
1130
|
-
// NOTE: the .toLowerCase() is unnecessary and causes https://github.com/angular/angular.js/issues/16624 for ng-attr-*
|
|
1131
|
-
nName = directiveNormalize(name.toLowerCase());
|
|
1132
|
-
attrsMap[nName] = name;
|
|
1133
|
-
|
|
1134
|
-
if (isNgAttr || !hasOwn(attrs, nName)) {
|
|
1135
|
-
attrs[nName] = value;
|
|
1136
|
-
if (getBooleanAttrName(node, nName)) {
|
|
1137
|
-
attrs[nName] = true; // presence means true
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
addAttrInterpolateDirective(
|
|
1142
|
-
node,
|
|
1143
|
-
directives,
|
|
1144
|
-
value,
|
|
1145
|
-
nName,
|
|
1146
|
-
isNgAttr,
|
|
1147
|
-
);
|
|
1148
|
-
|
|
1149
|
-
if (nName !== ignoreDirective) {
|
|
1150
|
-
addDirective(directives, nName, "A", maxPriority);
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
|
|
1155
|
-
if (
|
|
1156
|
-
nodeName === "input" &&
|
|
1157
|
-
node.getAttribute("type") === "hidden"
|
|
1158
|
-
) {
|
|
1159
|
-
// Hidden input elements can have strange behaviour when navigating back to the page
|
|
1160
|
-
// This tells the browser not to try to cache and reinstate previous values
|
|
1161
|
-
node.setAttribute("autocomplete", "off");
|
|
1162
|
-
}
|
|
1163
|
-
|
|
1164
|
-
break;
|
|
1165
|
-
case Node.TEXT_NODE:
|
|
1166
|
-
addTextInterpolateDirective(directives, node.nodeValue);
|
|
1167
|
-
break;
|
|
1168
|
-
default:
|
|
1169
|
-
break;
|
|
1170
|
-
}
|
|
1171
|
-
|
|
1172
|
-
directives.sort(byPriority);
|
|
1173
|
-
return directives;
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
/**
|
|
1177
|
-
* A function generator that is used to support both eager and lazy compilation
|
|
1178
|
-
* linking function.
|
|
1179
|
-
* @param eager
|
|
1180
|
-
* @param {NodeList|Node} compileNodes
|
|
1181
|
-
* @param transcludeFn
|
|
1182
|
-
* @param maxPriority
|
|
1183
|
-
* @param ignoreDirective
|
|
1184
|
-
* @param previousCompileContext
|
|
1185
|
-
* @returns {PublicLinkFn|TranscludeFn}
|
|
1186
|
-
*/
|
|
1187
|
-
function compilationGenerator(
|
|
1188
|
-
eager,
|
|
1189
|
-
compileNodes,
|
|
1190
|
-
transcludeFn,
|
|
1191
|
-
maxPriority,
|
|
1192
|
-
ignoreDirective,
|
|
1193
|
-
previousCompileContext,
|
|
1194
|
-
) {
|
|
1195
|
-
let compiled;
|
|
1196
|
-
if (eager) {
|
|
1197
|
-
return compile(
|
|
1198
|
-
compileNodes,
|
|
1199
|
-
transcludeFn,
|
|
1200
|
-
maxPriority,
|
|
1201
|
-
ignoreDirective,
|
|
1202
|
-
previousCompileContext,
|
|
1203
|
-
);
|
|
1204
|
-
}
|
|
1205
|
-
|
|
1206
|
-
return function lazyCompilation() {
|
|
1207
|
-
if (!compiled) {
|
|
1208
|
-
compiled = compile(
|
|
1209
|
-
compileNodes,
|
|
1210
|
-
transcludeFn,
|
|
1211
|
-
maxPriority,
|
|
1212
|
-
ignoreDirective,
|
|
1213
|
-
previousCompileContext,
|
|
1214
|
-
);
|
|
1215
|
-
|
|
1216
|
-
// Null out all of these references for garbage collection
|
|
1217
|
-
compileNodes = transcludeFn = previousCompileContext = null;
|
|
1218
|
-
}
|
|
1219
|
-
return compiled.apply(this, arguments);
|
|
1220
|
-
};
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
/**
|
|
1224
|
-
* Once the directives have been collected, their compile functions are executed. This method
|
|
1225
|
-
* is responsible for inlining directive templates as well as terminating the application
|
|
1226
|
-
* of the directives if the terminal directive has been reached.
|
|
1227
|
-
*
|
|
1228
|
-
* @param {Array} directives Array of collected directives to execute their compile function.
|
|
1229
|
-
* this needs to be pre-sorted by priority order.
|
|
1230
|
-
* @param {Node | Element} compileNode DOM node to apply the compile functions to
|
|
1231
|
-
* @param {Attributes} templateAttrs The shared attribute function
|
|
1232
|
-
* @param {TranscludeFn} transcludeFn
|
|
1233
|
-
* @param {Object=} originalReplaceDirective An optional directive that will be ignored when
|
|
1234
|
-
* compiling the transclusion.
|
|
1235
|
-
* @param {Array.<Function>} [preLinkFns]
|
|
1236
|
-
* @param {Array.<Function>} [postLinkFns]
|
|
1237
|
-
* @param {Object} [previousCompileContext] Context used for previous compilation of the current
|
|
1238
|
-
* node
|
|
1239
|
-
* @returns {NodeLinkFnCtx} node link function
|
|
1240
|
-
*/
|
|
1241
|
-
function applyDirectivesToNode(
|
|
1242
|
-
directives,
|
|
1243
|
-
compileNode,
|
|
1244
|
-
templateAttrs,
|
|
1245
|
-
transcludeFn,
|
|
1246
|
-
originalReplaceDirective,
|
|
1247
|
-
preLinkFns,
|
|
1248
|
-
postLinkFns,
|
|
1249
|
-
previousCompileContext,
|
|
1250
|
-
) {
|
|
1251
|
-
previousCompileContext = previousCompileContext || {};
|
|
1252
|
-
|
|
1253
|
-
let terminalPriority = -Number.MAX_VALUE;
|
|
1254
|
-
let terminal = false;
|
|
1255
|
-
let {
|
|
1256
|
-
newScopeDirective,
|
|
1257
|
-
controllerDirectives,
|
|
1258
|
-
newIsolateScopeDirective,
|
|
1259
|
-
templateDirective,
|
|
1260
|
-
nonTlbTranscludeDirective,
|
|
1261
|
-
hasElementTranscludeDirective,
|
|
1262
|
-
ctxNodeRef,
|
|
1263
|
-
parentNodeRef,
|
|
1264
|
-
} = previousCompileContext;
|
|
1265
|
-
let hasTranscludeDirective = false;
|
|
1266
|
-
let hasTemplate = false;
|
|
1267
|
-
let compileNodeRef = new NodeRef(compileNode);
|
|
1268
|
-
const index = previousCompileContext.index;
|
|
1269
|
-
templateAttrs.$nodeRef = compileNodeRef;
|
|
1270
|
-
let directive;
|
|
1271
|
-
let directiveName;
|
|
1272
|
-
let $template;
|
|
1273
|
-
let replaceDirective = originalReplaceDirective;
|
|
1274
|
-
/** @type {TranscludeFn} */
|
|
1275
|
-
let childTranscludeFn = transcludeFn;
|
|
1276
|
-
|
|
1277
|
-
let didScanForMultipleTransclusion = false;
|
|
1278
|
-
let mightHaveMultipleTransclusionError = false;
|
|
1279
|
-
let directiveValue;
|
|
1280
|
-
|
|
1281
|
-
/**
|
|
1282
|
-
* Links all the directives of a single node.
|
|
1283
|
-
* @type {NodeLinkFn}
|
|
1284
|
-
*/
|
|
1285
|
-
// @ts-ignore
|
|
1286
|
-
let nodeLinkFn = function (
|
|
1287
|
-
childLinkFn,
|
|
1288
|
-
scope,
|
|
1289
|
-
linkNode,
|
|
1290
|
-
boundTranscludeFn,
|
|
1291
|
-
) {
|
|
1292
|
-
let i;
|
|
1293
|
-
let ii;
|
|
1294
|
-
let isolateScope;
|
|
1295
|
-
let controllerScope;
|
|
1296
|
-
let elementControllers;
|
|
1297
|
-
let transcludeFn;
|
|
1298
|
-
let scopeToChild = scope;
|
|
1299
|
-
|
|
1300
|
-
/** @type {NodeRef} */
|
|
1301
|
-
let $element;
|
|
1302
|
-
/** @type {Attributes} */
|
|
1303
|
-
let attrs;
|
|
1304
|
-
let scopeBindingInfo;
|
|
1305
|
-
|
|
1306
|
-
if (compileNode === linkNode) {
|
|
1307
|
-
attrs = templateAttrs;
|
|
1308
|
-
$element = templateAttrs.$nodeRef;
|
|
1309
|
-
} else {
|
|
1310
|
-
$element = new NodeRef(linkNode);
|
|
1311
|
-
attrs = new Attributes(
|
|
1312
|
-
$rootScope,
|
|
1313
|
-
$animate,
|
|
1314
|
-
$exceptionHandler,
|
|
1315
|
-
$sce,
|
|
1316
|
-
$element,
|
|
1317
|
-
templateAttrs,
|
|
1318
|
-
);
|
|
1319
|
-
}
|
|
1320
|
-
|
|
1321
|
-
controllerScope = scope;
|
|
1322
|
-
if (newIsolateScopeDirective) {
|
|
1323
|
-
isolateScope = scope.$newIsolate();
|
|
1324
|
-
} else if (newScopeDirective) {
|
|
1325
|
-
controllerScope = scope.$parent;
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
if (boundTranscludeFn) {
|
|
1329
|
-
// track `boundTranscludeFn` so it can be unwrapped if `transcludeFn`
|
|
1330
|
-
// is later passed as `parentBoundTranscludeFn` to `publicLinkFn`
|
|
1331
|
-
transcludeFn = controllersBoundTransclude;
|
|
1332
|
-
transcludeFn["$$boundTransclude"] = boundTranscludeFn;
|
|
1333
|
-
// expose the slots on the `$transclude` function
|
|
1334
|
-
transcludeFn["isSlotFilled"] = function (slotName) {
|
|
1335
|
-
return !!boundTranscludeFn.$$slots[slotName];
|
|
1336
|
-
};
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
if (controllerDirectives) {
|
|
1340
|
-
elementControllers = setupControllers(
|
|
1341
|
-
$element,
|
|
1342
|
-
attrs,
|
|
1343
|
-
transcludeFn,
|
|
1344
|
-
controllerDirectives,
|
|
1345
|
-
isolateScope,
|
|
1346
|
-
scope,
|
|
1347
|
-
newIsolateScopeDirective,
|
|
1348
|
-
);
|
|
1349
|
-
}
|
|
1350
|
-
|
|
1351
|
-
if (newIsolateScopeDirective) {
|
|
1352
|
-
isolateScope.$target.$$isolateBindings =
|
|
1353
|
-
newIsolateScopeDirective.$$isolateBindings;
|
|
1354
|
-
scopeBindingInfo = initializeDirectiveBindings(
|
|
1355
|
-
scope,
|
|
1356
|
-
attrs,
|
|
1357
|
-
isolateScope,
|
|
1358
|
-
isolateScope.$$isolateBindings,
|
|
1359
|
-
newIsolateScopeDirective,
|
|
1360
|
-
);
|
|
1361
|
-
if (scopeBindingInfo.removeWatches) {
|
|
1362
|
-
isolateScope.$on("$destroy", scopeBindingInfo.removeWatches);
|
|
1363
|
-
}
|
|
1364
|
-
}
|
|
1365
|
-
|
|
1366
|
-
// Initialize bindToController bindings
|
|
1367
|
-
for (const name in elementControllers) {
|
|
1368
|
-
const controllerDirective = controllerDirectives[name];
|
|
1369
|
-
const controller = elementControllers[name];
|
|
1370
|
-
const bindings = controllerDirective.$$bindings.bindToController;
|
|
1371
|
-
|
|
1372
|
-
// Controller instance is bound to the scope
|
|
1373
|
-
const controllerInstance = controller();
|
|
1374
|
-
controller.instance = controllerScope.$new(controllerInstance);
|
|
1375
|
-
setCacheData(
|
|
1376
|
-
$element.node,
|
|
1377
|
-
`$${controllerDirective.name}Controller`,
|
|
1378
|
-
controller.instance,
|
|
1379
|
-
);
|
|
1380
|
-
controller.bindingInfo = initializeDirectiveBindings(
|
|
1381
|
-
controllerScope,
|
|
1382
|
-
attrs,
|
|
1383
|
-
controller.instance,
|
|
1384
|
-
bindings,
|
|
1385
|
-
controllerDirective,
|
|
1386
|
-
);
|
|
1387
|
-
}
|
|
1388
|
-
|
|
1389
|
-
// Bind the required controllers to the controller, if `require` is an object and `bindToController` is truthy
|
|
1390
|
-
if (controllerDirectives) {
|
|
1391
|
-
Object.entries(controllerDirectives).forEach(
|
|
1392
|
-
([name, controllerDirective]) => {
|
|
1393
|
-
const { require } = controllerDirective;
|
|
1394
|
-
if (
|
|
1395
|
-
controllerDirective.bindToController &&
|
|
1396
|
-
!Array.isArray(require) &&
|
|
1397
|
-
isObject(require)
|
|
1398
|
-
) {
|
|
1399
|
-
extend(
|
|
1400
|
-
elementControllers[name].instance,
|
|
1401
|
-
getControllers(
|
|
1402
|
-
name,
|
|
1403
|
-
require,
|
|
1404
|
-
$element.element,
|
|
1405
|
-
elementControllers,
|
|
1406
|
-
),
|
|
1407
|
-
);
|
|
1408
|
-
}
|
|
1409
|
-
},
|
|
1410
|
-
);
|
|
1411
|
-
}
|
|
1412
|
-
|
|
1413
|
-
// Handle the init and destroy lifecycle hooks on all controllers that have them
|
|
1414
|
-
if (elementControllers) {
|
|
1415
|
-
Object.values(elementControllers).forEach((controller) => {
|
|
1416
|
-
const controllerInstance = controller.instance;
|
|
1417
|
-
if (isFunction(controllerInstance.$onChanges)) {
|
|
1418
|
-
try {
|
|
1419
|
-
controllerInstance.$onChanges(
|
|
1420
|
-
controller.bindingInfo.initialChanges,
|
|
1421
|
-
);
|
|
1422
|
-
} catch (e) {
|
|
1423
|
-
$exceptionHandler(e);
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
|
-
if (isFunction(controllerInstance.$onInit)) {
|
|
1427
|
-
try {
|
|
1428
|
-
controllerInstance.$target.$onInit();
|
|
1429
|
-
} catch (e) {
|
|
1430
|
-
$exceptionHandler(e);
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
if (isFunction(controllerInstance.$onDestroy)) {
|
|
1434
|
-
controllerScope.$on("$destroy", () => {
|
|
1435
|
-
controllerInstance.$onDestroy();
|
|
1436
|
-
});
|
|
1437
|
-
}
|
|
1438
|
-
});
|
|
1439
|
-
}
|
|
1440
|
-
|
|
1441
|
-
// PRELINKING
|
|
1442
|
-
for (i = 0, ii = preLinkFns.length; i < ii; i++) {
|
|
1443
|
-
let preLinkFn = preLinkFns[i];
|
|
1444
|
-
const controllers =
|
|
1445
|
-
preLinkFn["require"] &&
|
|
1446
|
-
getControllers(
|
|
1447
|
-
preLinkFn["directiveName"],
|
|
1448
|
-
preLinkFn["require"],
|
|
1449
|
-
$element.element,
|
|
1450
|
-
elementControllers,
|
|
1451
|
-
);
|
|
1452
|
-
|
|
1453
|
-
// invoke link function
|
|
1454
|
-
try {
|
|
1455
|
-
preLinkFn(
|
|
1456
|
-
preLinkFn["isolateScope"] ? isolateScope : scope,
|
|
1457
|
-
$element.node, // Prelink functions accept a Node
|
|
1458
|
-
attrs,
|
|
1459
|
-
controllers,
|
|
1460
|
-
transcludeFn,
|
|
1461
|
-
);
|
|
1462
|
-
} catch (e) {
|
|
1463
|
-
$exceptionHandler(e, startingTag($element.getAny()));
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
|
|
1467
|
-
// RECURSION
|
|
1468
|
-
// We only pass the isolate scope, if the isolate directive has a template,
|
|
1469
|
-
// otherwise the child elements do not belong to the isolate directive.
|
|
1470
|
-
|
|
1471
|
-
if (
|
|
1472
|
-
newIsolateScopeDirective &&
|
|
1473
|
-
(newIsolateScopeDirective.template ||
|
|
1474
|
-
newIsolateScopeDirective.templateUrl === null)
|
|
1475
|
-
) {
|
|
1476
|
-
scopeToChild = isolateScope;
|
|
1477
|
-
}
|
|
1478
|
-
if (
|
|
1479
|
-
childLinkFn &&
|
|
1480
|
-
linkNode &&
|
|
1481
|
-
linkNode.childNodes &&
|
|
1482
|
-
linkNode.childNodes.length
|
|
1483
|
-
) {
|
|
1484
|
-
childLinkFn(
|
|
1485
|
-
scopeToChild,
|
|
1486
|
-
new NodeRef(linkNode.childNodes),
|
|
1487
|
-
boundTranscludeFn,
|
|
1488
|
-
);
|
|
1489
|
-
}
|
|
1490
|
-
// POSTLINKING
|
|
1491
|
-
for (i = postLinkFns.length - 1; i >= 0; i--) {
|
|
1492
|
-
let postLinkFn = postLinkFns[i];
|
|
1493
|
-
const controllers =
|
|
1494
|
-
postLinkFn["require"] &&
|
|
1495
|
-
getControllers(
|
|
1496
|
-
postLinkFn["directiveName"],
|
|
1497
|
-
postLinkFn["require"],
|
|
1498
|
-
/** @type {Element} */ ($element.node),
|
|
1499
|
-
elementControllers,
|
|
1500
|
-
);
|
|
1501
|
-
|
|
1502
|
-
// invoke link function
|
|
1503
|
-
try {
|
|
1504
|
-
if (postLinkFn["isolateScope"]) {
|
|
1505
|
-
setIsolateScope($element.element, isolateScope);
|
|
1506
|
-
}
|
|
1507
|
-
|
|
1508
|
-
postLinkFn(
|
|
1509
|
-
postLinkFn["isolateScope"] ? isolateScope : scope,
|
|
1510
|
-
$element.node,
|
|
1511
|
-
attrs,
|
|
1512
|
-
controllers,
|
|
1513
|
-
transcludeFn,
|
|
1514
|
-
);
|
|
1515
|
-
} catch (e) {
|
|
1516
|
-
$exceptionHandler(e, startingTag($element.getAny()));
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
if (elementControllers) {
|
|
1521
|
-
// Trigger $postLink lifecycle hooks
|
|
1522
|
-
Object.values(elementControllers).forEach((controller) => {
|
|
1523
|
-
const controllerInstance = controller.instance;
|
|
1524
|
-
if (isFunction(controllerInstance.$postLink)) {
|
|
1525
|
-
controllerInstance.$postLink();
|
|
1526
|
-
}
|
|
1527
|
-
});
|
|
1528
|
-
}
|
|
1529
|
-
|
|
1530
|
-
// This is the function that is injected as `$transclude` or
|
|
1531
|
-
// the fifth parameter to the link function.
|
|
1532
|
-
// Example: function link (scope, element, attrs, ctrl, transclude) {}
|
|
1533
|
-
// Note: all arguments are optional!
|
|
1534
|
-
function controllersBoundTransclude(
|
|
1535
|
-
scope,
|
|
1536
|
-
cloneAttachFn,
|
|
1537
|
-
futureParentElement,
|
|
1538
|
-
slotName,
|
|
1539
|
-
) {
|
|
1540
|
-
let transcludeControllers;
|
|
1541
|
-
// No scope passed in:
|
|
1542
|
-
if (!isScope(scope)) {
|
|
1543
|
-
slotName = futureParentElement;
|
|
1544
|
-
futureParentElement = cloneAttachFn;
|
|
1545
|
-
cloneAttachFn = scope;
|
|
1546
|
-
scope = undefined;
|
|
1547
|
-
}
|
|
1548
|
-
if (hasElementTranscludeDirective) {
|
|
1549
|
-
transcludeControllers = elementControllers;
|
|
1550
|
-
}
|
|
1551
|
-
if (!futureParentElement) {
|
|
1552
|
-
futureParentElement = hasElementTranscludeDirective
|
|
1553
|
-
? $element.node.parentElement
|
|
1554
|
-
: $element.node;
|
|
1555
|
-
}
|
|
1556
|
-
if (slotName) {
|
|
1557
|
-
// slotTranscludeFn can be one of three things:
|
|
1558
|
-
// * a transclude function - a filled slot
|
|
1559
|
-
// * `null` - an optional slot that was not filled
|
|
1560
|
-
// * `undefined` - a slot that was not declared (i.e. invalid)
|
|
1561
|
-
const slotTranscludeFn = boundTranscludeFn.$$slots[slotName];
|
|
1562
|
-
if (slotTranscludeFn) {
|
|
1563
|
-
return slotTranscludeFn(
|
|
1564
|
-
scope,
|
|
1565
|
-
cloneAttachFn,
|
|
1566
|
-
transcludeControllers,
|
|
1567
|
-
futureParentElement,
|
|
1568
|
-
scopeToChild,
|
|
1569
|
-
);
|
|
1570
|
-
}
|
|
1571
|
-
|
|
1572
|
-
if (isUndefined(slotTranscludeFn)) {
|
|
1573
|
-
throw $compileMinErr(
|
|
1574
|
-
"noslot",
|
|
1575
|
-
'No parent directive that requires a transclusion with slot name "{0}". ' +
|
|
1576
|
-
"Element: {1}",
|
|
1577
|
-
slotName,
|
|
1578
|
-
startingTag($element.element),
|
|
1579
|
-
);
|
|
1580
|
-
}
|
|
1581
|
-
} else {
|
|
1582
|
-
return boundTranscludeFn(
|
|
1583
|
-
scope,
|
|
1584
|
-
cloneAttachFn,
|
|
1585
|
-
transcludeControllers,
|
|
1586
|
-
futureParentElement,
|
|
1587
|
-
scopeToChild,
|
|
1588
|
-
);
|
|
1589
|
-
}
|
|
1590
|
-
}
|
|
1591
|
-
};
|
|
1592
|
-
|
|
1593
|
-
// executes all directives on the current element
|
|
1594
|
-
for (let i = 0, ii = directives.length; i < ii; i++) {
|
|
1595
|
-
directive = directives[i];
|
|
1596
|
-
$template = undefined;
|
|
1597
|
-
|
|
1598
|
-
if (terminalPriority > directive.priority) {
|
|
1599
|
-
break; // prevent further processing of directives
|
|
1600
|
-
}
|
|
1601
|
-
|
|
1602
|
-
directiveValue = directive.scope;
|
|
1603
|
-
|
|
1604
|
-
if (directiveValue) {
|
|
1605
|
-
// skip the check for directives with async templates, we'll check the derived sync
|
|
1606
|
-
// directive when the template arrives
|
|
1607
|
-
if (!directive.templateUrl) {
|
|
1608
|
-
if (isObject(directiveValue)) {
|
|
1609
|
-
// This directive is trying to add an isolated scope.
|
|
1610
|
-
// Check that there is no scope of any kind already
|
|
1611
|
-
assertNoDuplicate(
|
|
1612
|
-
"new/isolated scope",
|
|
1613
|
-
newIsolateScopeDirective || newScopeDirective,
|
|
1614
|
-
directive,
|
|
1615
|
-
compileNodeRef,
|
|
1616
|
-
);
|
|
1617
|
-
newIsolateScopeDirective = directive;
|
|
1618
|
-
} else {
|
|
1619
|
-
// This directive is trying to add a child scope.
|
|
1620
|
-
// Check that there is no isolated scope already
|
|
1621
|
-
assertNoDuplicate(
|
|
1622
|
-
"new/isolated scope",
|
|
1623
|
-
newIsolateScopeDirective,
|
|
1624
|
-
directive,
|
|
1625
|
-
compileNodeRef,
|
|
1626
|
-
);
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
|
|
1630
|
-
newScopeDirective = newScopeDirective || directive;
|
|
1631
|
-
}
|
|
1632
|
-
|
|
1633
|
-
directiveName = directive.name;
|
|
1634
|
-
|
|
1635
|
-
// If we encounter a condition that can result in transclusion on the directive,
|
|
1636
|
-
// then scan ahead in the remaining directives for others that may cause a multiple
|
|
1637
|
-
// transclusion error to be thrown during the compilation process. If a matching directive
|
|
1638
|
-
// is found, then we know that when we encounter a transcluded directive, we need to eagerly
|
|
1639
|
-
// compile the `transclude` function rather than doing it lazily in order to throw
|
|
1640
|
-
// exceptions at the correct time
|
|
1641
|
-
const hasReplacedTemplate =
|
|
1642
|
-
directive.replace &&
|
|
1643
|
-
(directive.templateUrl || directive.template);
|
|
1644
|
-
const shouldTransclude =
|
|
1645
|
-
directive.transclude &&
|
|
1646
|
-
!EXCLUDED_DIRECTIVES.includes(directive.name);
|
|
1647
|
-
if (
|
|
1648
|
-
!didScanForMultipleTransclusion &&
|
|
1649
|
-
(hasReplacedTemplate || shouldTransclude)
|
|
1650
|
-
) {
|
|
1651
|
-
let candidateDirective;
|
|
1652
|
-
|
|
1653
|
-
for (
|
|
1654
|
-
let scanningIndex = i + 1;
|
|
1655
|
-
(candidateDirective = directives[scanningIndex++]);
|
|
1656
|
-
|
|
1657
|
-
) {
|
|
1658
|
-
if (
|
|
1659
|
-
(candidateDirective.transclude &&
|
|
1660
|
-
!EXCLUDED_DIRECTIVES.includes(candidateDirective.name)) ||
|
|
1661
|
-
(candidateDirective.replace &&
|
|
1662
|
-
(candidateDirective.templateUrl ||
|
|
1663
|
-
candidateDirective.template))
|
|
1664
|
-
) {
|
|
1665
|
-
mightHaveMultipleTransclusionError = true;
|
|
1666
|
-
break;
|
|
1667
|
-
}
|
|
1668
|
-
}
|
|
1669
|
-
|
|
1670
|
-
didScanForMultipleTransclusion = true;
|
|
1671
|
-
}
|
|
1672
|
-
|
|
1673
|
-
if (!directive.templateUrl && directive.controller) {
|
|
1674
|
-
controllerDirectives =
|
|
1675
|
-
controllerDirectives || Object.create(null);
|
|
1676
|
-
assertNoDuplicate(
|
|
1677
|
-
`'${directiveName}' controller`,
|
|
1678
|
-
controllerDirectives[directiveName],
|
|
1679
|
-
directive,
|
|
1680
|
-
compileNodeRef,
|
|
1681
|
-
);
|
|
1682
|
-
controllerDirectives[directiveName] = directive;
|
|
1683
|
-
}
|
|
1684
|
-
|
|
1685
|
-
directiveValue = directive.transclude;
|
|
1686
|
-
|
|
1687
|
-
if (directiveValue) {
|
|
1688
|
-
hasTranscludeDirective = true;
|
|
1689
|
-
|
|
1690
|
-
// Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
|
|
1691
|
-
// This option should only be used by directives that know how to safely handle element transclusion,
|
|
1692
|
-
// where the transcluded nodes are added or replaced after linking.
|
|
1693
|
-
if (!EXCLUDED_DIRECTIVES.includes(directive.name)) {
|
|
1694
|
-
assertNoDuplicate(
|
|
1695
|
-
"transclusion",
|
|
1696
|
-
nonTlbTranscludeDirective,
|
|
1697
|
-
directive,
|
|
1698
|
-
compileNodeRef,
|
|
1699
|
-
);
|
|
1700
|
-
nonTlbTranscludeDirective = directive;
|
|
1701
|
-
}
|
|
1702
|
-
|
|
1703
|
-
if (directiveValue === "element") {
|
|
1704
|
-
hasElementTranscludeDirective = true;
|
|
1705
|
-
terminalPriority = directive.priority;
|
|
1706
|
-
$template = compileNodeRef;
|
|
1707
|
-
compileNodeRef = new NodeRef(document.createComment(""));
|
|
1708
|
-
templateAttrs.$nodeRef = compileNodeRef;
|
|
1709
|
-
compileNode = compileNodeRef.node;
|
|
1710
|
-
ctxNodeRef.node = compileNode;
|
|
1711
|
-
replaceWith(
|
|
1712
|
-
new NodeRef($template.getAny()),
|
|
1713
|
-
compileNode,
|
|
1714
|
-
index,
|
|
1715
|
-
);
|
|
1716
|
-
|
|
1717
|
-
// @ts-ignore
|
|
1718
|
-
childTranscludeFn = compilationGenerator(
|
|
1719
|
-
mightHaveMultipleTransclusionError,
|
|
1720
|
-
$template.getAny(),
|
|
1721
|
-
transcludeFn,
|
|
1722
|
-
terminalPriority,
|
|
1723
|
-
replaceDirective && replaceDirective.name,
|
|
1724
|
-
{
|
|
1725
|
-
// Don't pass in:
|
|
1726
|
-
// - controllerDirectives - otherwise we'll create duplicates controllers
|
|
1727
|
-
// - newIsolateScopeDirective or templateDirective - combining templates with
|
|
1728
|
-
// element transclusion doesn't make sense.
|
|
1729
|
-
//
|
|
1730
|
-
// We need only nonTlbTranscludeDirective so that we prevent putting transclusion
|
|
1731
|
-
// on the same element more than once.
|
|
1732
|
-
nonTlbTranscludeDirective,
|
|
1733
|
-
},
|
|
1734
|
-
);
|
|
1735
|
-
} else {
|
|
1736
|
-
const slots = Object.create(null);
|
|
1737
|
-
|
|
1738
|
-
if (!isObject(directiveValue)) {
|
|
1739
|
-
//
|
|
1740
|
-
// Clone childnodes before clearing contents on transcluded directives
|
|
1741
|
-
$template = compileNode.cloneNode(true).childNodes;
|
|
1742
|
-
} else {
|
|
1743
|
-
// We have transclusion slots,
|
|
1744
|
-
// collect them up, compile them and store their transclusion functions
|
|
1745
|
-
$template = document.createDocumentFragment();
|
|
1746
|
-
|
|
1747
|
-
const slotMap = Object.create(null);
|
|
1748
|
-
const filledSlots = Object.create(null);
|
|
1749
|
-
|
|
1750
|
-
// Parse the element selectors
|
|
1751
|
-
Object.entries(directiveValue).forEach(
|
|
1752
|
-
([slotName, elementSelector]) => {
|
|
1753
|
-
// If an element selector starts with a ? then it is optional
|
|
1754
|
-
const optional = elementSelector.charAt(0) === "?";
|
|
1755
|
-
elementSelector = optional
|
|
1756
|
-
? elementSelector.substring(1)
|
|
1757
|
-
: elementSelector;
|
|
1758
|
-
|
|
1759
|
-
slotMap[elementSelector] = slotName;
|
|
1760
|
-
|
|
1761
|
-
// We explicitly assign `null` since this implies that a slot was defined but not filled.
|
|
1762
|
-
// Later when calling boundTransclusion functions with a slot name we only error if the
|
|
1763
|
-
// slot is `undefined`
|
|
1764
|
-
slots[slotName] = null;
|
|
1765
|
-
|
|
1766
|
-
// filledSlots contains `true` for all slots that are either optional or have been
|
|
1767
|
-
// filled. This is used to check that we have not missed any required slots
|
|
1768
|
-
filledSlots[slotName] = optional;
|
|
1769
|
-
},
|
|
1770
|
-
);
|
|
1771
|
-
|
|
1772
|
-
// Add the matching elements into their slot
|
|
1773
|
-
compileNodeRef.element.childNodes.forEach((node) => {
|
|
1774
|
-
const slotName =
|
|
1775
|
-
slotMap[
|
|
1776
|
-
directiveNormalize(
|
|
1777
|
-
getNodeName(/** @type {Element} */ (node)),
|
|
1778
|
-
)
|
|
1779
|
-
];
|
|
1780
|
-
if (slotName) {
|
|
1781
|
-
filledSlots[slotName] = true;
|
|
1782
|
-
slots[slotName] =
|
|
1783
|
-
slots[slotName] || document.createDocumentFragment();
|
|
1784
|
-
slots[slotName].appendChild(node);
|
|
1785
|
-
} else {
|
|
1786
|
-
$template.appendChild(node);
|
|
1787
|
-
}
|
|
1788
|
-
});
|
|
1789
|
-
|
|
1790
|
-
// Check for required slots that were not filled
|
|
1791
|
-
Object.entries(filledSlots).forEach(([slotName, filled]) => {
|
|
1792
|
-
if (!filled) {
|
|
1793
|
-
throw $compileMinErr(
|
|
1794
|
-
"reqslot",
|
|
1795
|
-
"Required transclusion slot `{0}` was not filled.",
|
|
1796
|
-
slotName,
|
|
1797
|
-
);
|
|
1798
|
-
}
|
|
1799
|
-
});
|
|
1800
|
-
|
|
1801
|
-
for (const slotName in slots) {
|
|
1802
|
-
if (slots[slotName]) {
|
|
1803
|
-
// Only define a transclusion function if the slot was filled
|
|
1804
|
-
const slotCompileNodes = slots[slotName].childNodes;
|
|
1805
|
-
slots[slotName] = compilationGenerator(
|
|
1806
|
-
mightHaveMultipleTransclusionError,
|
|
1807
|
-
slotCompileNodes,
|
|
1808
|
-
transcludeFn,
|
|
1809
|
-
);
|
|
1810
|
-
}
|
|
1811
|
-
}
|
|
1812
|
-
|
|
1813
|
-
$template = $template.childNodes;
|
|
1814
|
-
}
|
|
1815
|
-
|
|
1816
|
-
emptyElement(/** @type {Element} */ (compileNode)); // clear contents on transcluded directives
|
|
1817
|
-
|
|
1818
|
-
// lazily compile transcluded template and generate a transcluded link function
|
|
1819
|
-
// @ts-ignore
|
|
1820
|
-
childTranscludeFn = compilationGenerator(
|
|
1821
|
-
mightHaveMultipleTransclusionError,
|
|
1822
|
-
$template,
|
|
1823
|
-
transcludeFn,
|
|
1824
|
-
undefined,
|
|
1825
|
-
undefined,
|
|
1826
|
-
{
|
|
1827
|
-
needsNewScope:
|
|
1828
|
-
directive.$$isolateScope || directive.$$newScope,
|
|
1829
|
-
},
|
|
1830
|
-
);
|
|
1831
|
-
childTranscludeFn["$$slots"] = slots;
|
|
1832
|
-
}
|
|
1833
|
-
}
|
|
1834
|
-
|
|
1835
|
-
if (directive.template) {
|
|
1836
|
-
hasTemplate = true;
|
|
1837
|
-
assertNoDuplicate(
|
|
1838
|
-
"template",
|
|
1839
|
-
templateDirective,
|
|
1840
|
-
directive,
|
|
1841
|
-
compileNodeRef,
|
|
1842
|
-
);
|
|
1843
|
-
templateDirective = directive;
|
|
1844
|
-
|
|
1845
|
-
directiveValue = isFunction(directive.template)
|
|
1846
|
-
? directive.template(compileNodeRef.node, templateAttrs)
|
|
1847
|
-
: directive.template;
|
|
1848
|
-
|
|
1849
|
-
directiveValue = denormalizeTemplate(directiveValue);
|
|
1850
|
-
if (directive.replace) {
|
|
1851
|
-
replaceDirective = directive;
|
|
1852
|
-
if (isTextNode(directiveValue)) {
|
|
1853
|
-
$template = [];
|
|
1854
|
-
} else {
|
|
1855
|
-
$template = removeComments(
|
|
1856
|
-
wrapTemplate(
|
|
1857
|
-
directive.templateNamespace,
|
|
1858
|
-
trim(directiveValue),
|
|
1859
|
-
),
|
|
1860
|
-
);
|
|
1861
|
-
}
|
|
1862
|
-
|
|
1863
|
-
if (isString($template)) {
|
|
1864
|
-
$template = Array.from(
|
|
1865
|
-
createNodelistFromHTML($template),
|
|
1866
|
-
).filter((x) => x.nodeType === Node.ELEMENT_NODE);
|
|
1867
|
-
}
|
|
1868
|
-
compileNode = $template[0];
|
|
1869
|
-
|
|
1870
|
-
if (
|
|
1871
|
-
$template.length !== 1 ||
|
|
1872
|
-
compileNode.nodeType !== Node.ELEMENT_NODE
|
|
1873
|
-
) {
|
|
1874
|
-
throw $compileMinErr(
|
|
1875
|
-
"tplrt",
|
|
1876
|
-
"Template for directive '{0}' must have exactly one root element. {1}",
|
|
1877
|
-
directiveName,
|
|
1878
|
-
"",
|
|
1879
|
-
);
|
|
1880
|
-
}
|
|
1881
|
-
|
|
1882
|
-
replaceWith(compileNodeRef, compileNode);
|
|
1883
|
-
|
|
1884
|
-
if (parentNodeRef) {
|
|
1885
|
-
parentNodeRef.setIndex(index, compileNode);
|
|
1886
|
-
}
|
|
1887
|
-
|
|
1888
|
-
const newTemplateAttrs = { $attr: {} };
|
|
1889
|
-
|
|
1890
|
-
// combine directives from the original node and from the template:
|
|
1891
|
-
// - take the array of directives for this element
|
|
1892
|
-
// - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)
|
|
1893
|
-
// - collect directives from the template and sort them by priority
|
|
1894
|
-
// - combine directives as: processed + template + unprocessed
|
|
1895
|
-
const templateDirectives = collectDirectives(
|
|
1896
|
-
/** @type {Element} */ (compileNode),
|
|
1897
|
-
newTemplateAttrs,
|
|
1898
|
-
);
|
|
1899
|
-
const unprocessedDirectives = directives.splice(
|
|
1900
|
-
i + 1,
|
|
1901
|
-
directives.length - (i + 1),
|
|
1902
|
-
);
|
|
1903
|
-
|
|
1904
|
-
if (newIsolateScopeDirective || newScopeDirective) {
|
|
1905
|
-
// The original directive caused the current element to be replaced but this element
|
|
1906
|
-
// also needs to have a new scope, so we need to tell the template directives
|
|
1907
|
-
// that they would need to get their scope from further up, if they require transclusion
|
|
1908
|
-
markDirectiveScope(
|
|
1909
|
-
templateDirectives,
|
|
1910
|
-
newIsolateScopeDirective,
|
|
1911
|
-
newScopeDirective,
|
|
1912
|
-
);
|
|
1913
|
-
}
|
|
1914
|
-
directives = directives
|
|
1915
|
-
.concat(templateDirectives)
|
|
1916
|
-
.concat(unprocessedDirectives);
|
|
1917
|
-
|
|
1918
|
-
mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
|
|
1919
|
-
|
|
1920
|
-
ii = directives.length;
|
|
1921
|
-
} else {
|
|
1922
|
-
if (compileNodeRef.isElement()) {
|
|
1923
|
-
compileNodeRef.element.innerHTML = directiveValue;
|
|
1924
|
-
}
|
|
1925
|
-
}
|
|
1926
|
-
}
|
|
1927
|
-
|
|
1928
|
-
if (directive.templateUrl) {
|
|
1929
|
-
hasTemplate = true;
|
|
1930
|
-
assertNoDuplicate(
|
|
1931
|
-
"template",
|
|
1932
|
-
templateDirective,
|
|
1933
|
-
directive,
|
|
1934
|
-
compileNodeRef,
|
|
1935
|
-
);
|
|
1936
|
-
templateDirective = directive;
|
|
1937
|
-
|
|
1938
|
-
if (directive.replace) {
|
|
1939
|
-
replaceDirective = directive;
|
|
1940
|
-
}
|
|
1941
|
-
// @ts-ignore
|
|
1942
|
-
nodeLinkFn = compileTemplateUrl(
|
|
1943
|
-
directives.splice(i, directives.length - i),
|
|
1944
|
-
compileNodeRef,
|
|
1945
|
-
templateAttrs,
|
|
1946
|
-
/** @type {Element} */ (compileNode),
|
|
1947
|
-
hasTranscludeDirective && childTranscludeFn,
|
|
1948
|
-
preLinkFns,
|
|
1949
|
-
postLinkFns,
|
|
1950
|
-
{
|
|
1951
|
-
index,
|
|
1952
|
-
controllerDirectives,
|
|
1953
|
-
newScopeDirective:
|
|
1954
|
-
newScopeDirective !== directive && newScopeDirective,
|
|
1955
|
-
newIsolateScopeDirective,
|
|
1956
|
-
templateDirective,
|
|
1957
|
-
nonTlbTranscludeDirective,
|
|
1958
|
-
futureParentElement:
|
|
1959
|
-
previousCompileContext.futureParentElement,
|
|
1960
|
-
},
|
|
1961
|
-
);
|
|
1962
|
-
ii = directives.length;
|
|
1963
|
-
} else if (directive.compile) {
|
|
1964
|
-
try {
|
|
1965
|
-
/** @type {PublicLinkFn} */
|
|
1966
|
-
const linkFn = directive.compile(
|
|
1967
|
-
compileNodeRef.getAny(),
|
|
1968
|
-
templateAttrs,
|
|
1969
|
-
childTranscludeFn,
|
|
1970
|
-
);
|
|
1971
|
-
const context = directive.$$originalDirective || directive;
|
|
1972
|
-
if (isFunction(linkFn)) {
|
|
1973
|
-
addLinkFns(null, bind(context, linkFn));
|
|
1974
|
-
} else if (linkFn) {
|
|
1975
|
-
addLinkFns(
|
|
1976
|
-
bind(context, linkFn["pre"]),
|
|
1977
|
-
bind(context, linkFn["post"]),
|
|
1978
|
-
);
|
|
1979
|
-
}
|
|
1980
|
-
} catch (e) {
|
|
1981
|
-
$exceptionHandler(e, startingTag(compileNodeRef.getAny()));
|
|
1982
|
-
}
|
|
1983
|
-
}
|
|
1984
|
-
|
|
1985
|
-
if (directive.terminal) {
|
|
1986
|
-
terminal = true;
|
|
1987
|
-
terminalPriority = Math.max(terminalPriority, directive.priority);
|
|
1988
|
-
}
|
|
1989
|
-
}
|
|
1990
|
-
|
|
1991
|
-
previousCompileContext.hasElementTranscludeDirective =
|
|
1992
|
-
hasElementTranscludeDirective;
|
|
1993
|
-
|
|
1994
|
-
// might be normal or delayed nodeLinkFn depending on if templateUrl is present
|
|
1995
|
-
return {
|
|
1996
|
-
nodeLinkFn,
|
|
1997
|
-
terminal,
|
|
1998
|
-
transclude: childTranscludeFn,
|
|
1999
|
-
transcludeOnThisElement: hasTranscludeDirective,
|
|
2000
|
-
templateOnThisElement: hasTemplate,
|
|
2001
|
-
newScope: newScopeDirective && newScopeDirective.scope === true,
|
|
2002
|
-
};
|
|
2003
|
-
|
|
2004
|
-
/// /////////////////
|
|
2005
|
-
function addLinkFns(pre, post) {
|
|
2006
|
-
if (pre) {
|
|
2007
|
-
pre.require = directive.require;
|
|
2008
|
-
pre.directiveName = directiveName;
|
|
2009
|
-
if (
|
|
2010
|
-
newIsolateScopeDirective === directive ||
|
|
2011
|
-
directive.$$isolateScope
|
|
2012
|
-
) {
|
|
2013
|
-
pre = cloneAndAnnotateFn(pre, { isolateScope: true });
|
|
2014
|
-
}
|
|
2015
|
-
preLinkFns.push(pre);
|
|
2016
|
-
}
|
|
2017
|
-
if (post) {
|
|
2018
|
-
post.require = directive.require;
|
|
2019
|
-
post.directiveName = directiveName;
|
|
2020
|
-
if (
|
|
2021
|
-
newIsolateScopeDirective === directive ||
|
|
2022
|
-
directive.$$isolateScope
|
|
2023
|
-
) {
|
|
2024
|
-
post = cloneAndAnnotateFn(post, { isolateScope: true });
|
|
2025
|
-
}
|
|
2026
|
-
postLinkFns.push(post);
|
|
2027
|
-
}
|
|
2028
|
-
}
|
|
2029
|
-
}
|
|
2030
|
-
|
|
2031
|
-
/**
|
|
2032
|
-
*
|
|
2033
|
-
* @param {*} directiveName
|
|
2034
|
-
* @param {*} require
|
|
2035
|
-
* @param {Element} $element
|
|
2036
|
-
* @param {*} elementControllers
|
|
2037
|
-
* @returns
|
|
2038
|
-
*/
|
|
2039
|
-
function getControllers(
|
|
2040
|
-
directiveName,
|
|
2041
|
-
require,
|
|
2042
|
-
$element,
|
|
2043
|
-
elementControllers,
|
|
2044
|
-
) {
|
|
2045
|
-
let value;
|
|
2046
|
-
|
|
2047
|
-
if (isString(require)) {
|
|
2048
|
-
const match = require.match(REQUIRE_PREFIX_REGEXP);
|
|
2049
|
-
const name = require.substring(match[0].length);
|
|
2050
|
-
const inheritType = match[1] || match[3];
|
|
2051
|
-
const optional = match[2] === "?";
|
|
2052
|
-
|
|
2053
|
-
// If only parents then start at the parent element
|
|
2054
|
-
if (inheritType === "^^") {
|
|
2055
|
-
if ($element.parentElement) {
|
|
2056
|
-
$element = $element.parentElement;
|
|
2057
|
-
} else {
|
|
2058
|
-
$element = undefined;
|
|
2059
|
-
}
|
|
2060
|
-
// Otherwise attempt getting the controller from elementControllers in case
|
|
2061
|
-
// the element is transcluded (and has no data) and to avoid .data if possible
|
|
2062
|
-
} else {
|
|
2063
|
-
value = elementControllers && elementControllers[name];
|
|
2064
|
-
value = value && value.instance;
|
|
2065
|
-
}
|
|
2066
|
-
|
|
2067
|
-
if (!value) {
|
|
2068
|
-
const dataName = `$${name}Controller`;
|
|
2069
|
-
if (
|
|
2070
|
-
inheritType === "^^" &&
|
|
2071
|
-
$element &&
|
|
2072
|
-
$element.nodeType === Node.DOCUMENT_NODE
|
|
2073
|
-
) {
|
|
2074
|
-
// inheritedData() uses the documentElement when it finds the document, so we would
|
|
2075
|
-
// require from the element itself.
|
|
2076
|
-
value = null;
|
|
2077
|
-
} else {
|
|
2078
|
-
value = $element
|
|
2079
|
-
? inheritType
|
|
2080
|
-
? getInheritedData($element, dataName)
|
|
2081
|
-
: getCacheData($element, dataName)
|
|
2082
|
-
: undefined;
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
if (!value && !optional) {
|
|
2086
|
-
throw $compileMinErr(
|
|
2087
|
-
"ctreq",
|
|
2088
|
-
"Controller '{0}', required by directive '{1}', can't be found!",
|
|
2089
|
-
name,
|
|
2090
|
-
directiveName,
|
|
2091
|
-
);
|
|
2092
|
-
}
|
|
2093
|
-
} else if (Array.isArray(require)) {
|
|
2094
|
-
value = [];
|
|
2095
|
-
for (let i = 0, ii = require.length; i < ii; i++) {
|
|
2096
|
-
value[i] = getControllers(
|
|
2097
|
-
directiveName,
|
|
2098
|
-
require[i],
|
|
2099
|
-
$element,
|
|
2100
|
-
elementControllers,
|
|
2101
|
-
);
|
|
2102
|
-
}
|
|
2103
|
-
} else if (isObject(require)) {
|
|
2104
|
-
value = {};
|
|
2105
|
-
Object.entries(require).forEach(([property, controller]) => {
|
|
2106
|
-
value[property] = getControllers(
|
|
2107
|
-
directiveName,
|
|
2108
|
-
controller,
|
|
2109
|
-
$element,
|
|
2110
|
-
elementControllers,
|
|
2111
|
-
);
|
|
2112
|
-
});
|
|
2113
|
-
}
|
|
2114
|
-
|
|
2115
|
-
return value || null;
|
|
2116
|
-
}
|
|
2117
|
-
|
|
2118
|
-
/**
|
|
2119
|
-
* @param {NodeRef} $element
|
|
2120
|
-
* @param attrs
|
|
2121
|
-
* @param transcludeFn
|
|
2122
|
-
* @param controllerDirectives
|
|
2123
|
-
* @param isolateScope
|
|
2124
|
-
* @param scope
|
|
2125
|
-
* @param newIsolateScopeDirective
|
|
2126
|
-
* @returns {any}
|
|
2127
|
-
*/
|
|
2128
|
-
function setupControllers(
|
|
2129
|
-
$element,
|
|
2130
|
-
attrs,
|
|
2131
|
-
transcludeFn,
|
|
2132
|
-
controllerDirectives,
|
|
2133
|
-
isolateScope,
|
|
2134
|
-
scope,
|
|
2135
|
-
newIsolateScopeDirective,
|
|
2136
|
-
) {
|
|
2137
|
-
const elementControllers = Object.create(null);
|
|
2138
|
-
for (const controllerKey in controllerDirectives) {
|
|
2139
|
-
const directive = controllerDirectives[controllerKey];
|
|
2140
|
-
const locals = {
|
|
2141
|
-
$scope:
|
|
2142
|
-
directive === newIsolateScopeDirective ||
|
|
2143
|
-
directive.$$isolateScope
|
|
2144
|
-
? isolateScope
|
|
2145
|
-
: scope,
|
|
2146
|
-
$element: $element.node,
|
|
2147
|
-
$attrs: attrs,
|
|
2148
|
-
$transclude: transcludeFn,
|
|
2149
|
-
};
|
|
2150
|
-
|
|
2151
|
-
let { controller } = directive;
|
|
2152
|
-
if (controller === "@") {
|
|
2153
|
-
controller = attrs[directive.name];
|
|
2154
|
-
}
|
|
2155
|
-
|
|
2156
|
-
const controllerInstance = $controller(
|
|
2157
|
-
controller,
|
|
2158
|
-
locals,
|
|
2159
|
-
true,
|
|
2160
|
-
directive.controllerAs,
|
|
2161
|
-
);
|
|
2162
|
-
|
|
2163
|
-
// For directives with element transclusion the element is a comment.
|
|
2164
|
-
// In this case .data will not attach any data.
|
|
2165
|
-
// Instead, we save the controllers for the element in a local hash and attach to .data
|
|
2166
|
-
// later, once we have the actual element.
|
|
2167
|
-
elementControllers[directive.name] = controllerInstance;
|
|
2168
|
-
if ($element.isElement()) {
|
|
2169
|
-
setCacheData(
|
|
2170
|
-
$element.element,
|
|
2171
|
-
`$${directive.name}Controller`,
|
|
2172
|
-
controllerInstance.instance,
|
|
2173
|
-
);
|
|
2174
|
-
}
|
|
2175
|
-
}
|
|
2176
|
-
return elementControllers;
|
|
2177
|
-
}
|
|
2178
|
-
|
|
2179
|
-
// Depending upon the context in which a directive finds itself it might need to have a new isolated
|
|
2180
|
-
// or child scope created. For instance:
|
|
2181
|
-
// * if the directive has been pulled into a template because another directive with a higher priority
|
|
2182
|
-
// asked for element transclusion
|
|
2183
|
-
// * if the directive itself asks for transclusion but it is at the root of a template and the original
|
|
2184
|
-
// element was replaced. See https://github.com/angular/angular.js/issues/12936
|
|
2185
|
-
function markDirectiveScope(directives, isolateScope, newScope) {
|
|
2186
|
-
for (let j = 0, jj = directives.length; j < jj; j++) {
|
|
2187
|
-
directives[j] = inherit(directives[j], {
|
|
2188
|
-
$$isolateScope: isolateScope,
|
|
2189
|
-
$$newScope: newScope,
|
|
2190
|
-
});
|
|
2191
|
-
}
|
|
2192
|
-
}
|
|
2193
|
-
|
|
2194
|
-
/**
|
|
2195
|
-
* looks up the directive and decorates it with exception handling and proper parameters. We
|
|
2196
|
-
* call this the boundDirective.
|
|
2197
|
-
*
|
|
2198
|
-
* @param {string} name name of the directive to look up.
|
|
2199
|
-
* @param {string} location The directive must be found in specific format.
|
|
2200
|
-
* String containing any of these characters:
|
|
2201
|
-
*
|
|
2202
|
-
* * `E`: element name
|
|
2203
|
-
* * `A': attribute
|
|
2204
|
-
* @returns {boolean} true if directive was added.
|
|
2205
|
-
*/
|
|
2206
|
-
function addDirective(tDirectives, name, location, maxPriority) {
|
|
2207
|
-
let match = false;
|
|
2208
|
-
if (hasOwn(hasDirectives, name)) {
|
|
2209
|
-
for (
|
|
2210
|
-
let directive,
|
|
2211
|
-
directives = $injector.get(name + DirectiveSuffix),
|
|
2212
|
-
i = 0,
|
|
2213
|
-
ii = directives.length;
|
|
2214
|
-
i < ii;
|
|
2215
|
-
i++
|
|
2216
|
-
) {
|
|
2217
|
-
directive = directives[i];
|
|
2218
|
-
if (
|
|
2219
|
-
(isUndefined(maxPriority) ||
|
|
2220
|
-
maxPriority > directive.priority) &&
|
|
2221
|
-
directive.restrict.indexOf(location) !== -1
|
|
2222
|
-
) {
|
|
2223
|
-
if (!directive.$$bindings) {
|
|
2224
|
-
const bindings = (directive.$$bindings =
|
|
2225
|
-
parseDirectiveBindings(directive, directive.name));
|
|
2226
|
-
if (isObject(bindings.isolateScope)) {
|
|
2227
|
-
directive.$$isolateBindings = bindings.isolateScope;
|
|
2228
|
-
}
|
|
2229
|
-
}
|
|
2230
|
-
tDirectives.push(directive);
|
|
2231
|
-
match = directive;
|
|
2232
|
-
}
|
|
2233
|
-
}
|
|
2234
|
-
}
|
|
2235
|
-
return match;
|
|
2236
|
-
}
|
|
2237
|
-
|
|
2238
|
-
/**
|
|
2239
|
-
* When the element is replaced with HTML template then the new attributes
|
|
2240
|
-
* on the template need to be merged with the existing attributes in the DOM.
|
|
2241
|
-
* The desired effect is to have both of the attributes present.
|
|
2242
|
-
*
|
|
2243
|
-
* @param {object} dst destination attributes (original DOM)
|
|
2244
|
-
* @param {object} src source attributes (from the directive template)
|
|
2245
|
-
*/
|
|
2246
|
-
function mergeTemplateAttributes(dst, src) {
|
|
2247
|
-
const srcAttr = src.$attr;
|
|
2248
|
-
const dstAttr = dst.$attr;
|
|
2249
|
-
|
|
2250
|
-
// reapply the old attributes to the new element
|
|
2251
|
-
Object.entries(dst).forEach(([key, value]) => {
|
|
2252
|
-
if (key.charAt(0) !== "$") {
|
|
2253
|
-
if (src[key] && src[key] !== value) {
|
|
2254
|
-
if (value.length) {
|
|
2255
|
-
value += (key === "style" ? ";" : " ") + src[key];
|
|
2256
|
-
} else {
|
|
2257
|
-
value = src[key];
|
|
2258
|
-
}
|
|
2259
|
-
}
|
|
2260
|
-
dst.$set(key, value, true, srcAttr[key]);
|
|
2261
|
-
}
|
|
2262
|
-
});
|
|
2263
|
-
|
|
2264
|
-
// copy the new attributes on the old attrs object
|
|
2265
|
-
Object.entries(src).forEach(([key, value]) => {
|
|
2266
|
-
// Check if we already set this attribute in the loop above.
|
|
2267
|
-
// `dst` will never contain hasOwnProperty as DOM parser won't let it.
|
|
2268
|
-
// You will get an "InvalidCharacterError: DOM Exception 5" error if you
|
|
2269
|
-
// have an attribute like "has-own-property" or "data-has-own-property", etc.
|
|
2270
|
-
if (!hasOwn(dst, key) && key.charAt(0) !== "$") {
|
|
2271
|
-
dst[key] = value;
|
|
2272
|
-
|
|
2273
|
-
if (key !== "class" && key !== "style") {
|
|
2274
|
-
dstAttr[key] = srcAttr[key];
|
|
2275
|
-
}
|
|
2276
|
-
}
|
|
2277
|
-
});
|
|
2278
|
-
}
|
|
2279
|
-
|
|
2280
|
-
/**
|
|
2281
|
-
*
|
|
2282
|
-
* @param {import("../../interface.ts").Directive[]} directives
|
|
2283
|
-
* @param {NodeRef} $compileNode
|
|
2284
|
-
* @param {Attributes} tAttrs
|
|
2285
|
-
* @param {Element} $rootElement
|
|
2286
|
-
* @param {*} childTranscludeFn
|
|
2287
|
-
* @param {Array} preLinkFns
|
|
2288
|
-
* @param {Array} postLinkFns
|
|
2289
|
-
* @param {*} previousCompileContext
|
|
2290
|
-
* @returns
|
|
2291
|
-
*/
|
|
2292
|
-
function compileTemplateUrl(
|
|
2293
|
-
directives,
|
|
2294
|
-
$compileNode,
|
|
2295
|
-
tAttrs,
|
|
2296
|
-
$rootElement,
|
|
2297
|
-
childTranscludeFn,
|
|
2298
|
-
preLinkFns,
|
|
2299
|
-
postLinkFns,
|
|
2300
|
-
previousCompileContext,
|
|
2301
|
-
) {
|
|
2302
|
-
let linkQueue = [];
|
|
2303
|
-
/** @type {any} */
|
|
2304
|
-
let afterTemplateNodeLinkFn;
|
|
2305
|
-
let afterTemplateChildLinkFn;
|
|
2306
|
-
let afterTemplateNodeLinkFnCtx;
|
|
2307
|
-
const beforeTemplateCompileNode = $compileNode.getAny();
|
|
2308
|
-
const origAsyncDirective = directives.shift();
|
|
2309
|
-
const derivedSyncDirective = inherit(origAsyncDirective, {
|
|
2310
|
-
templateUrl: null,
|
|
2311
|
-
transclude: null,
|
|
2312
|
-
replace: null,
|
|
2313
|
-
$$originalDirective: origAsyncDirective,
|
|
2314
|
-
});
|
|
2315
|
-
const templateUrl = isFunction(origAsyncDirective.templateUrl)
|
|
2316
|
-
? /** @type { ((element: Element, tAttrs: Attributes) => string) } */ (
|
|
2317
|
-
origAsyncDirective.templateUrl
|
|
2318
|
-
)($compileNode.element, tAttrs)
|
|
2319
|
-
: origAsyncDirective.templateUrl;
|
|
2320
|
-
const { templateNamespace } = origAsyncDirective;
|
|
2321
|
-
|
|
2322
|
-
emptyElement($compileNode.element);
|
|
2323
|
-
|
|
2324
|
-
$templateRequest(templateUrl)
|
|
2325
|
-
.then((content) => {
|
|
2326
|
-
/** @type {Element} */
|
|
2327
|
-
let compileNode;
|
|
2328
|
-
let tempTemplateAttrs;
|
|
2329
|
-
let $template;
|
|
2330
|
-
let childBoundTranscludeFn;
|
|
2331
|
-
|
|
2332
|
-
content = denormalizeTemplate(content);
|
|
2333
|
-
|
|
2334
|
-
if (origAsyncDirective.replace) {
|
|
2335
|
-
if (isTextNode(content)) {
|
|
2336
|
-
$template = [];
|
|
2337
|
-
} else if (isString(content)) {
|
|
2338
|
-
$template = Array.from(
|
|
2339
|
-
createNodelistFromHTML(content),
|
|
2340
|
-
).filter(
|
|
2341
|
-
(node) =>
|
|
2342
|
-
node.nodeType !== Node.COMMENT_NODE &&
|
|
2343
|
-
node.nodeType !== Node.TEXT_NODE,
|
|
2344
|
-
);
|
|
2345
|
-
} else {
|
|
2346
|
-
$template = removeComments(
|
|
2347
|
-
wrapTemplate(templateNamespace, trim(content)),
|
|
2348
|
-
);
|
|
2349
|
-
}
|
|
2350
|
-
compileNode = $template[0];
|
|
2351
|
-
if (
|
|
2352
|
-
$template.length !== 1 ||
|
|
2353
|
-
compileNode.nodeType !== Node.ELEMENT_NODE
|
|
2354
|
-
) {
|
|
2355
|
-
throw $compileMinErr(
|
|
2356
|
-
"tplrt",
|
|
2357
|
-
"Template for directive '{0}' must have exactly one root element. {1}",
|
|
2358
|
-
origAsyncDirective.name,
|
|
2359
|
-
templateUrl,
|
|
2360
|
-
);
|
|
2361
|
-
}
|
|
2362
|
-
|
|
2363
|
-
tempTemplateAttrs = { $attr: {} };
|
|
2364
|
-
|
|
2365
|
-
replaceWith(
|
|
2366
|
-
$compileNode,
|
|
2367
|
-
compileNode,
|
|
2368
|
-
previousCompileContext.index,
|
|
2369
|
-
);
|
|
2370
|
-
|
|
2371
|
-
const templateDirectives = collectDirectives(
|
|
2372
|
-
compileNode,
|
|
2373
|
-
tempTemplateAttrs,
|
|
2374
|
-
);
|
|
2375
|
-
|
|
2376
|
-
if (isObject(origAsyncDirective.scope)) {
|
|
2377
|
-
// the original directive that caused the template to be loaded async required
|
|
2378
|
-
// an isolate scope
|
|
2379
|
-
markDirectiveScope(templateDirectives, true);
|
|
2380
|
-
}
|
|
2381
|
-
directives = templateDirectives.concat(directives);
|
|
2382
|
-
|
|
2383
|
-
mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
|
|
2384
|
-
} else {
|
|
2385
|
-
compileNode = /** @type {Element} */ (
|
|
2386
|
-
beforeTemplateCompileNode
|
|
2387
|
-
);
|
|
2388
|
-
$compileNode.element.innerHTML = content;
|
|
2389
|
-
}
|
|
2390
|
-
|
|
2391
|
-
directives.unshift(derivedSyncDirective);
|
|
2392
|
-
afterTemplateNodeLinkFnCtx = applyDirectivesToNode(
|
|
2393
|
-
directives,
|
|
2394
|
-
compileNode,
|
|
2395
|
-
tAttrs,
|
|
2396
|
-
childTranscludeFn,
|
|
2397
|
-
origAsyncDirective,
|
|
2398
|
-
preLinkFns,
|
|
2399
|
-
postLinkFns,
|
|
2400
|
-
{ ...previousCompileContext, ctxNodeRef: $compileNode },
|
|
2401
|
-
);
|
|
2402
|
-
|
|
2403
|
-
afterTemplateNodeLinkFn = afterTemplateNodeLinkFnCtx?.nodeLinkFn;
|
|
2404
|
-
if ($rootElement) {
|
|
2405
|
-
Object.entries($rootElement).forEach(([i, node]) => {
|
|
2406
|
-
if (node === compileNode) {
|
|
2407
|
-
$rootElement[i] = $compileNode;
|
|
2408
|
-
}
|
|
2409
|
-
});
|
|
2410
|
-
}
|
|
2411
|
-
afterTemplateChildLinkFn = compileNodes(
|
|
2412
|
-
new NodeRef($compileNode.getAny().childNodes),
|
|
2413
|
-
childTranscludeFn,
|
|
2414
|
-
);
|
|
2415
|
-
|
|
2416
|
-
while (linkQueue.length) {
|
|
2417
|
-
const scope = linkQueue.shift();
|
|
2418
|
-
const beforeTemplateLinkNode = linkQueue.shift();
|
|
2419
|
-
const boundTranscludeFn = linkQueue.shift();
|
|
2420
|
-
let linkNode = $compileNode.getAny();
|
|
2421
|
-
|
|
2422
|
-
if (scope.$$destroyed) {
|
|
2423
|
-
continue;
|
|
2424
|
-
}
|
|
2425
|
-
|
|
2426
|
-
if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
|
|
2427
|
-
const oldClasses = beforeTemplateLinkNode.className;
|
|
2428
|
-
|
|
2429
|
-
if (
|
|
2430
|
-
!(
|
|
2431
|
-
previousCompileContext.hasElementTranscludeDirective &&
|
|
2432
|
-
origAsyncDirective.replace
|
|
2433
|
-
)
|
|
2434
|
-
) {
|
|
2435
|
-
// it was cloned therefore we have to clone as well.
|
|
2436
|
-
linkNode = compileNode.cloneNode(true);
|
|
2437
|
-
beforeTemplateLinkNode.appendChild(linkNode);
|
|
2438
|
-
}
|
|
2439
|
-
// Copy in CSS classes from original node
|
|
2440
|
-
try {
|
|
2441
|
-
if (oldClasses !== "") {
|
|
2442
|
-
$compileNode.element.classList.forEach((cls) =>
|
|
2443
|
-
beforeTemplateLinkNode.classList.add(cls),
|
|
2444
|
-
);
|
|
2445
|
-
}
|
|
2446
|
-
} catch {
|
|
2447
|
-
// ignore, since it means that we are trying to set class on
|
|
2448
|
-
// SVG element, where class name is read-only.
|
|
2449
|
-
}
|
|
2450
|
-
}
|
|
2451
|
-
if (afterTemplateNodeLinkFnCtx.transcludeOnThisElement) {
|
|
2452
|
-
childBoundTranscludeFn = createBoundTranscludeFn(
|
|
2453
|
-
scope,
|
|
2454
|
-
afterTemplateNodeLinkFnCtx.transclude,
|
|
2455
|
-
boundTranscludeFn,
|
|
2456
|
-
);
|
|
2457
|
-
} else {
|
|
2458
|
-
childBoundTranscludeFn = boundTranscludeFn;
|
|
2459
|
-
}
|
|
2460
|
-
|
|
2461
|
-
afterTemplateNodeLinkFn(
|
|
2462
|
-
afterTemplateChildLinkFn,
|
|
2463
|
-
scope,
|
|
2464
|
-
linkNode,
|
|
2465
|
-
childBoundTranscludeFn,
|
|
2466
|
-
);
|
|
2467
|
-
}
|
|
2468
|
-
linkQueue = null;
|
|
2469
|
-
})
|
|
2470
|
-
.catch((error) => {
|
|
2471
|
-
if (isError(error)) {
|
|
2472
|
-
$exceptionHandler(error);
|
|
2473
|
-
} else {
|
|
2474
|
-
$exceptionHandler(new Error(error));
|
|
2475
|
-
}
|
|
2476
|
-
});
|
|
2477
|
-
|
|
2478
|
-
return function delayedNodeLinkFn(
|
|
2479
|
-
_ignoreChildLinkFn,
|
|
2480
|
-
scope,
|
|
2481
|
-
node,
|
|
2482
|
-
rootElement,
|
|
2483
|
-
boundTranscludeFn,
|
|
2484
|
-
) {
|
|
2485
|
-
let childBoundTranscludeFn = boundTranscludeFn;
|
|
2486
|
-
if (scope.$$destroyed) {
|
|
2487
|
-
return;
|
|
2488
|
-
}
|
|
2489
|
-
if (linkQueue) {
|
|
2490
|
-
linkQueue.push(scope, node, rootElement);
|
|
2491
|
-
} else {
|
|
2492
|
-
if (afterTemplateNodeLinkFn.transcludeOnThisElement) {
|
|
2493
|
-
childBoundTranscludeFn = createBoundTranscludeFn(
|
|
2494
|
-
scope,
|
|
2495
|
-
afterTemplateNodeLinkFn.transclude,
|
|
2496
|
-
boundTranscludeFn,
|
|
2497
|
-
);
|
|
2498
|
-
}
|
|
2499
|
-
afterTemplateNodeLinkFn(
|
|
2500
|
-
afterTemplateChildLinkFn,
|
|
2501
|
-
scope,
|
|
2502
|
-
node,
|
|
2503
|
-
rootElement,
|
|
2504
|
-
childBoundTranscludeFn,
|
|
2505
|
-
);
|
|
2506
|
-
}
|
|
2507
|
-
};
|
|
2508
|
-
}
|
|
2509
|
-
|
|
2510
|
-
/**
|
|
2511
|
-
* Sorting function for bound directives.
|
|
2512
|
-
*/
|
|
2513
|
-
function byPriority(a, b) {
|
|
2514
|
-
const diff = b.priority - a.priority;
|
|
2515
|
-
if (diff !== 0) {
|
|
2516
|
-
return diff;
|
|
2517
|
-
}
|
|
2518
|
-
if (a.name !== b.name) {
|
|
2519
|
-
return a.name < b.name ? -1 : 1;
|
|
2520
|
-
}
|
|
2521
|
-
return a.index - b.index;
|
|
2522
|
-
}
|
|
2523
|
-
|
|
2524
|
-
function assertNoDuplicate(
|
|
2525
|
-
what,
|
|
2526
|
-
previousDirective,
|
|
2527
|
-
directive,
|
|
2528
|
-
element,
|
|
2529
|
-
) {
|
|
2530
|
-
function wrapModuleNameIfDefined(moduleName) {
|
|
2531
|
-
return moduleName ? ` (module: ${moduleName})` : "";
|
|
2532
|
-
}
|
|
2533
|
-
|
|
2534
|
-
if (previousDirective) {
|
|
2535
|
-
throw $compileMinErr(
|
|
2536
|
-
"multidir",
|
|
2537
|
-
"Multiple directives [{0}{1}, {2}{3}] asking for {4} on: {5}",
|
|
2538
|
-
previousDirective.name,
|
|
2539
|
-
wrapModuleNameIfDefined(previousDirective.$$moduleName),
|
|
2540
|
-
directive.name,
|
|
2541
|
-
wrapModuleNameIfDefined(directive.$$moduleName),
|
|
2542
|
-
what,
|
|
2543
|
-
startingTag(element.getAny()),
|
|
2544
|
-
);
|
|
2545
|
-
}
|
|
2546
|
-
}
|
|
2547
|
-
|
|
2548
|
-
function addTextInterpolateDirective(directives, text) {
|
|
2549
|
-
const interpolateFn = $interpolate(text, true);
|
|
2550
|
-
if (interpolateFn) {
|
|
2551
|
-
directives.push({
|
|
2552
|
-
priority: 0,
|
|
2553
|
-
compile: () => (scope, node) => {
|
|
2554
|
-
interpolateFn.expressions.forEach((x) => {
|
|
2555
|
-
scope.$watch(x, () => {
|
|
2556
|
-
const res = interpolateFn(
|
|
2557
|
-
isProxy(scope) ? scope.$target : scope,
|
|
2558
|
-
);
|
|
2559
|
-
switch (node.nodeType) {
|
|
2560
|
-
case 1:
|
|
2561
|
-
node.innerHTML = res;
|
|
2562
|
-
break;
|
|
2563
|
-
default:
|
|
2564
|
-
node.nodeValue = res;
|
|
2565
|
-
}
|
|
2566
|
-
});
|
|
2567
|
-
});
|
|
2568
|
-
},
|
|
2569
|
-
});
|
|
2570
|
-
}
|
|
2571
|
-
}
|
|
2572
|
-
|
|
2573
|
-
/**
|
|
2574
|
-
* @param {string} type
|
|
2575
|
-
* @param {string} template
|
|
2576
|
-
* @returns
|
|
2577
|
-
*/
|
|
2578
|
-
function wrapTemplate(type, template) {
|
|
2579
|
-
type = (type || "html").toLowerCase();
|
|
2580
|
-
switch (type) {
|
|
2581
|
-
case "svg":
|
|
2582
|
-
case "math": {
|
|
2583
|
-
const wrapper =
|
|
2584
|
-
/** @type {HTMLDivElement} */ document.createElement("div");
|
|
2585
|
-
wrapper.innerHTML = `<${type}>${template}</${type}>`;
|
|
2586
|
-
return wrapper.childNodes[0].childNodes;
|
|
2587
|
-
}
|
|
2588
|
-
default:
|
|
2589
|
-
return template;
|
|
2590
|
-
}
|
|
2591
|
-
}
|
|
2592
|
-
|
|
2593
|
-
function getTrustedAttrContext(nodeName, attrNormalizedName) {
|
|
2594
|
-
if (attrNormalizedName === "srcdoc") {
|
|
2595
|
-
return $sce.HTML;
|
|
2596
|
-
}
|
|
2597
|
-
// All nodes with src attributes require a RESOURCE_URL value, except for
|
|
2598
|
-
// img and various html5 media nodes, which require the MEDIA_URL context.
|
|
2599
|
-
if (attrNormalizedName === "src" || attrNormalizedName === "ngSrc") {
|
|
2600
|
-
if (
|
|
2601
|
-
["img", "video", "audio", "source", "track"].indexOf(nodeName) ===
|
|
2602
|
-
-1
|
|
2603
|
-
) {
|
|
2604
|
-
return $sce.RESOURCE_URL;
|
|
2605
|
-
}
|
|
2606
|
-
return $sce.MEDIA_URL;
|
|
2607
|
-
}
|
|
2608
|
-
if (attrNormalizedName === "xlinkHref") {
|
|
2609
|
-
// Some xlink:href are okay, most aren't
|
|
2610
|
-
if (nodeName === "image") {
|
|
2611
|
-
return $sce.MEDIA_URL;
|
|
2612
|
-
}
|
|
2613
|
-
if (nodeName === "a") {
|
|
2614
|
-
return $sce.URL;
|
|
2615
|
-
}
|
|
2616
|
-
return $sce.RESOURCE_URL;
|
|
2617
|
-
}
|
|
2618
|
-
if (
|
|
2619
|
-
// Formaction
|
|
2620
|
-
(nodeName === "form" && attrNormalizedName === "action") ||
|
|
2621
|
-
// If relative URLs can go where they are not expected to, then
|
|
2622
|
-
// all sorts of trust issues can arise.
|
|
2623
|
-
(nodeName === "base" && attrNormalizedName === "href") ||
|
|
2624
|
-
// links can be stylesheets or imports, which can run script in the current origin
|
|
2625
|
-
(nodeName === "link" && attrNormalizedName === "href")
|
|
2626
|
-
) {
|
|
2627
|
-
return $sce.RESOURCE_URL;
|
|
2628
|
-
}
|
|
2629
|
-
if (
|
|
2630
|
-
nodeName === "a" &&
|
|
2631
|
-
(attrNormalizedName === "href" || attrNormalizedName === "ngHref")
|
|
2632
|
-
) {
|
|
2633
|
-
return $sce.URL;
|
|
2634
|
-
}
|
|
2635
|
-
}
|
|
2636
|
-
|
|
2637
|
-
function getTrustedPropContext(nodeName, propNormalizedName) {
|
|
2638
|
-
const prop = propNormalizedName.toLowerCase();
|
|
2639
|
-
return (
|
|
2640
|
-
PROP_CONTEXTS[`${nodeName}|${prop}`] || PROP_CONTEXTS[`*|${prop}`]
|
|
2641
|
-
);
|
|
2642
|
-
}
|
|
2643
|
-
|
|
2644
|
-
function sanitizeSrcset(value, invokeType) {
|
|
2645
|
-
if (!value) {
|
|
2646
|
-
return value;
|
|
2647
|
-
}
|
|
2648
|
-
if (!isString(value)) {
|
|
2649
|
-
throw $compileMinErr(
|
|
2650
|
-
"srcset",
|
|
2651
|
-
'Can\'t pass trusted values to `{0}`: "{1}"',
|
|
2652
|
-
invokeType,
|
|
2653
|
-
value.toString(),
|
|
2654
|
-
);
|
|
2655
|
-
}
|
|
2656
|
-
|
|
2657
|
-
// Such values are a bit too complex to handle automatically inside $sce.
|
|
2658
|
-
// Instead, we sanitize each of the URIs individually, which works, even dynamically.
|
|
2659
|
-
// It's not possible to work around this using `$sce.trustAsMediaUrl`.
|
|
2660
|
-
// If you want to programmatically set explicitly trusted unsafe URLs, you should use
|
|
2661
|
-
// `$sce.trustAsHtml` on the whole `img` tag and inject it into the DOM using the
|
|
2662
|
-
// `ng-bind-html` directive.
|
|
2663
|
-
let result = "";
|
|
2664
|
-
|
|
2665
|
-
// first check if there are spaces because it's not the same pattern
|
|
2666
|
-
const trimmedSrcset = trim(value);
|
|
2667
|
-
// ( 999x ,| 999w ,| ,|, )
|
|
2668
|
-
const srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
|
|
2669
|
-
const pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;
|
|
2670
|
-
|
|
2671
|
-
// split srcset into tuple of uri and descriptor except for the last item
|
|
2672
|
-
const rawUris = trimmedSrcset.split(pattern);
|
|
2673
|
-
|
|
2674
|
-
// for each tuples
|
|
2675
|
-
const nbrUrisWith2parts = Math.floor(rawUris.length / 2);
|
|
2676
|
-
let i;
|
|
2677
|
-
for (i = 0; i < nbrUrisWith2parts; i++) {
|
|
2678
|
-
const innerIdx = i * 2;
|
|
2679
|
-
// sanitize the uri
|
|
2680
|
-
result += $sce.getTrustedMediaUrl(trim(rawUris[innerIdx]));
|
|
2681
|
-
// add the descriptor
|
|
2682
|
-
result += " " + trim(rawUris[innerIdx + 1]);
|
|
2683
|
-
}
|
|
2684
|
-
|
|
2685
|
-
// split the last item into uri and descriptor
|
|
2686
|
-
const lastTuple = trim(rawUris[i * 2]).split(/\s/);
|
|
2687
|
-
|
|
2688
|
-
// sanitize the last uri
|
|
2689
|
-
result += $sce.getTrustedMediaUrl(trim(lastTuple[0]));
|
|
2690
|
-
|
|
2691
|
-
// and add the last descriptor if any
|
|
2692
|
-
if (lastTuple.length === 2) {
|
|
2693
|
-
result += " " + trim(lastTuple[1]);
|
|
2694
|
-
}
|
|
2695
|
-
return result;
|
|
2696
|
-
}
|
|
2697
|
-
|
|
2698
|
-
function addPropertyDirective(node, directives, attrName, propName) {
|
|
2699
|
-
if (EVENT_HANDLER_ATTR_REGEXP.test(propName)) {
|
|
2700
|
-
throw $compileMinErr(
|
|
2701
|
-
"nodomevents",
|
|
2702
|
-
"Property bindings for HTML DOM event properties are disallowed",
|
|
2703
|
-
);
|
|
2704
|
-
}
|
|
2705
|
-
|
|
2706
|
-
const nodeName = getNodeName(node);
|
|
2707
|
-
const trustedContext = getTrustedPropContext(nodeName, propName);
|
|
2708
|
-
|
|
2709
|
-
let sanitizer = (x) => x;
|
|
2710
|
-
// Sanitize img[srcset] + source[srcset] values.
|
|
2711
|
-
if (
|
|
2712
|
-
propName === "srcset" &&
|
|
2713
|
-
(nodeName === "img" || nodeName === "source")
|
|
2714
|
-
) {
|
|
2715
|
-
sanitizer = (value) =>
|
|
2716
|
-
sanitizeSrcset($sce.valueOf(value), "ng-prop-srcset");
|
|
2717
|
-
} else if (trustedContext) {
|
|
2718
|
-
sanitizer = $sce.getTrusted.bind($sce, trustedContext);
|
|
2719
|
-
}
|
|
2720
|
-
|
|
2721
|
-
directives.push({
|
|
2722
|
-
priority: 100,
|
|
2723
|
-
compile: function ngPropCompileFn(_, attr) {
|
|
2724
|
-
const ngPropGetter = $parse(attr[attrName]);
|
|
2725
|
-
return {
|
|
2726
|
-
pre: function ngPropPreLinkFn(scope, $element) {
|
|
2727
|
-
function applyPropValue() {
|
|
2728
|
-
const propValue = ngPropGetter(scope);
|
|
2729
|
-
$element[propName] = sanitizer(propValue);
|
|
2730
|
-
}
|
|
2731
|
-
|
|
2732
|
-
applyPropValue();
|
|
2733
|
-
scope.$watch(propName, applyPropValue);
|
|
2734
|
-
scope.$watch(attr[attrName], (val) => {
|
|
2735
|
-
$sce.valueOf(val);
|
|
2736
|
-
applyPropValue();
|
|
2737
|
-
});
|
|
2738
|
-
},
|
|
2739
|
-
};
|
|
2740
|
-
},
|
|
2741
|
-
});
|
|
2742
|
-
}
|
|
2743
|
-
|
|
2744
|
-
function addAttrInterpolateDirective(
|
|
2745
|
-
node,
|
|
2746
|
-
directives,
|
|
2747
|
-
value,
|
|
2748
|
-
name,
|
|
2749
|
-
isNgAttr,
|
|
2750
|
-
) {
|
|
2751
|
-
const nodeName = getNodeName(node);
|
|
2752
|
-
const trustedContext = getTrustedAttrContext(nodeName, name);
|
|
2753
|
-
const mustHaveExpression = !isNgAttr;
|
|
2754
|
-
const allOrNothing = ALL_OR_NOTHING_ATTRS.includes(name) || isNgAttr;
|
|
2755
|
-
|
|
2756
|
-
let interpolateFn = $interpolate(
|
|
2757
|
-
value,
|
|
2758
|
-
mustHaveExpression,
|
|
2759
|
-
trustedContext,
|
|
2760
|
-
allOrNothing,
|
|
2761
|
-
);
|
|
2762
|
-
|
|
2763
|
-
// no interpolation found -> ignore
|
|
2764
|
-
if (!interpolateFn) {
|
|
2765
|
-
return;
|
|
2766
|
-
}
|
|
2767
|
-
|
|
2768
|
-
if (name === "multiple" && nodeName === "select") {
|
|
2769
|
-
throw $compileMinErr(
|
|
2770
|
-
"selmulti",
|
|
2771
|
-
"Binding to the 'multiple' attribute is not supported. Element: {0}",
|
|
2772
|
-
startingTag(node.outerHTML),
|
|
2773
|
-
);
|
|
2774
|
-
}
|
|
2775
|
-
|
|
2776
|
-
if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
|
|
2777
|
-
throw $compileMinErr(
|
|
2778
|
-
"nodomevents",
|
|
2779
|
-
"Interpolations for HTML DOM event attributes are disallowed",
|
|
2780
|
-
);
|
|
2781
|
-
}
|
|
2782
|
-
|
|
2783
|
-
directives.push({
|
|
2784
|
-
priority: 100,
|
|
2785
|
-
compile() {
|
|
2786
|
-
return {
|
|
2787
|
-
pre: function attrInterpolatePreLinkFn(scope, element, attr) {
|
|
2788
|
-
const $$observers =
|
|
2789
|
-
attr.$$observers ||
|
|
2790
|
-
(attr.$$observers = Object.create(null));
|
|
2791
|
-
|
|
2792
|
-
// If the attribute has changed since last $interpolate()ed
|
|
2793
|
-
const newValue = attr[name];
|
|
2794
|
-
if (newValue !== value) {
|
|
2795
|
-
// we need to interpolate again since the attribute value has been updated
|
|
2796
|
-
// (e.g. by another directive's compile function)
|
|
2797
|
-
// ensure unset/empty values make interpolateFn falsy
|
|
2798
|
-
interpolateFn =
|
|
2799
|
-
newValue &&
|
|
2800
|
-
$interpolate(
|
|
2801
|
-
newValue,
|
|
2802
|
-
true,
|
|
2803
|
-
trustedContext,
|
|
2804
|
-
allOrNothing,
|
|
2805
|
-
);
|
|
2806
|
-
value = newValue;
|
|
2807
|
-
}
|
|
2808
|
-
|
|
2809
|
-
// if attribute was updated so that there is no interpolation going on we don't want to
|
|
2810
|
-
// register any observers
|
|
2811
|
-
if (!interpolateFn) {
|
|
2812
|
-
return;
|
|
2813
|
-
}
|
|
2814
|
-
|
|
2815
|
-
// initialize attr object so that it's ready in case we need the value for isolate
|
|
2816
|
-
// scope initialization, otherwise the value would not be available from isolate
|
|
2817
|
-
// directive's linking fn during linking phase
|
|
2818
|
-
attr[name] = interpolateFn(scope);
|
|
2819
|
-
|
|
2820
|
-
($$observers[name] || ($$observers[name] = [])).$$inter =
|
|
2821
|
-
true;
|
|
2822
|
-
interpolateFn.expressions.forEach((x) => {
|
|
2823
|
-
const targetScope =
|
|
2824
|
-
(attr.$$observers && attr.$$observers[name].$$scope) ||
|
|
2825
|
-
scope;
|
|
2826
|
-
targetScope.$watch(x, () => {
|
|
2827
|
-
let newValue = interpolateFn(scope);
|
|
2828
|
-
// special case for class attribute addition + removal
|
|
2829
|
-
// so that class changes can tap into the animation
|
|
2830
|
-
// hooks provided by the $animate service. Be sure to
|
|
2831
|
-
// skip animations when the first digest occurs (when
|
|
2832
|
-
// both the new and the old values are the same) since
|
|
2833
|
-
// the CSS classes are the non-interpolated values
|
|
2834
|
-
if (name === "class") {
|
|
2835
|
-
attr.$updateClass(
|
|
2836
|
-
newValue,
|
|
2837
|
-
attr.$$element.classList.value,
|
|
2838
|
-
);
|
|
2839
|
-
} else {
|
|
2840
|
-
attr.$set(name, newValue);
|
|
2841
|
-
}
|
|
2842
|
-
});
|
|
2843
|
-
});
|
|
2844
|
-
|
|
2845
|
-
if (interpolateFn.expressions.length == 0) {
|
|
2846
|
-
// if there is nothing to watch, its a constant
|
|
2847
|
-
attr.$set(name, newValue);
|
|
2848
|
-
}
|
|
2849
|
-
},
|
|
2850
|
-
};
|
|
2851
|
-
},
|
|
2852
|
-
});
|
|
2853
|
-
}
|
|
2854
|
-
|
|
2855
|
-
/**
|
|
2856
|
-
*
|
|
2857
|
-
* @param {NodeRef} elementsToRemove The JQLite element which we are going to replace. We keep
|
|
2858
|
-
* the shell, but replace its DOM node reference.
|
|
2859
|
-
* @param {Node} newNode The new DOM node.
|
|
2860
|
-
* @param {number} [index] Parent node index.
|
|
2861
|
-
*/
|
|
2862
|
-
function replaceWith(elementsToRemove, newNode, index) {
|
|
2863
|
-
const firstElementToRemove = elementsToRemove.getAny();
|
|
2864
|
-
// const removeCount = elementsToRemove.length;
|
|
2865
|
-
const parent = firstElementToRemove.parentNode;
|
|
2866
|
-
|
|
2867
|
-
if (parent) {
|
|
2868
|
-
if (isDefined(index)) {
|
|
2869
|
-
const oldChild = parent.childNodes[index];
|
|
2870
|
-
if (oldChild) {
|
|
2871
|
-
parent.replaceChild(newNode, oldChild);
|
|
2872
|
-
}
|
|
2873
|
-
} else {
|
|
2874
|
-
parent.insertBefore(newNode, parent.firstChild);
|
|
2875
|
-
//parent.append(newNode);
|
|
2876
|
-
}
|
|
2877
|
-
}
|
|
2878
|
-
|
|
2879
|
-
// Append all the `elementsToRemove` to a fragment. This will...
|
|
2880
|
-
// - remove them from the DOM
|
|
2881
|
-
// - allow them to still be traversed with .nextSibling
|
|
2882
|
-
// - allow a single fragment.qSA to fetch all elements being removed
|
|
2883
|
-
const fragment = document.createDocumentFragment();
|
|
2884
|
-
elementsToRemove.collection().forEach((element) => {
|
|
2885
|
-
fragment.appendChild(element);
|
|
2886
|
-
});
|
|
2887
|
-
|
|
2888
|
-
elementsToRemove.node = newNode;
|
|
2889
|
-
}
|
|
2890
|
-
|
|
2891
|
-
function cloneAndAnnotateFn(fn, annotation) {
|
|
2892
|
-
return extend(
|
|
2893
|
-
function () {
|
|
2894
|
-
return fn.apply(null, arguments);
|
|
2895
|
-
},
|
|
2896
|
-
fn,
|
|
2897
|
-
annotation,
|
|
2898
|
-
);
|
|
2899
|
-
}
|
|
2900
|
-
|
|
2901
|
-
function strictBindingsCheck(attrName, directiveName) {
|
|
2902
|
-
if (strictComponentBindingsEnabled) {
|
|
2903
|
-
throw $compileMinErr(
|
|
2904
|
-
"missingattr",
|
|
2905
|
-
"Attribute '{0}' of '{1}' is non-optional and must be set!",
|
|
2906
|
-
attrName,
|
|
2907
|
-
directiveName,
|
|
2908
|
-
);
|
|
2909
|
-
}
|
|
2910
|
-
}
|
|
2911
|
-
|
|
2912
|
-
// Set up $watches for isolate scope and controller bindings.
|
|
2913
|
-
/**
|
|
2914
|
-
*
|
|
2915
|
-
* @param {import('../scope/scope.js').Scope} scope
|
|
2916
|
-
* @param {*} attrs
|
|
2917
|
-
* @param {import('../scope/scope.js').Scope} destination - child scope or isolate scope
|
|
2918
|
-
* @param {*} bindings
|
|
2919
|
-
* @param {*} directive
|
|
2920
|
-
* @returns
|
|
2921
|
-
*/
|
|
2922
|
-
function initializeDirectiveBindings(
|
|
2923
|
-
scope,
|
|
2924
|
-
attrs,
|
|
2925
|
-
destination,
|
|
2926
|
-
bindings,
|
|
2927
|
-
directive,
|
|
2928
|
-
) {
|
|
2929
|
-
const removeWatchCollection = [];
|
|
2930
|
-
const initialChanges = {};
|
|
2931
|
-
let changes;
|
|
2932
|
-
|
|
2933
|
-
if (bindings) {
|
|
2934
|
-
Object.entries(bindings).forEach(([scopeName, definition]) => {
|
|
2935
|
-
const {
|
|
2936
|
-
attrName,
|
|
2937
|
-
optional,
|
|
2938
|
-
mode, // @, =, <, or &
|
|
2939
|
-
} = definition;
|
|
2940
|
-
let lastValue;
|
|
2941
|
-
let parentGet;
|
|
2942
|
-
let parentSet;
|
|
2943
|
-
let compare;
|
|
2944
|
-
let removeWatch;
|
|
2945
|
-
let firstCall = true;
|
|
2946
|
-
let firstChange = true;
|
|
2947
|
-
|
|
2948
|
-
switch (mode) {
|
|
2949
|
-
case "@":
|
|
2950
|
-
if (!optional && !hasOwn(attrs, attrName)) {
|
|
2951
|
-
strictBindingsCheck(attrName, directive.name);
|
|
2952
|
-
destination[scopeName] = attrs[attrName] = undefined;
|
|
2953
|
-
}
|
|
2954
|
-
|
|
2955
|
-
removeWatch = attrs.$observe(attrName, (value) => {
|
|
2956
|
-
if (isString(value) || isBoolean(value)) {
|
|
2957
|
-
recordChanges(scopeName, value, firstChange);
|
|
2958
|
-
|
|
2959
|
-
destination[scopeName] = value;
|
|
2960
|
-
if (firstCall) {
|
|
2961
|
-
firstCall = false;
|
|
2962
|
-
} else {
|
|
2963
|
-
triggerOnChangesHook();
|
|
2964
|
-
firstChange = false;
|
|
2965
|
-
}
|
|
2966
|
-
}
|
|
2967
|
-
});
|
|
2968
|
-
attrs.$$observers[attrName].$$scope = scope;
|
|
2969
|
-
lastValue = attrs[attrName];
|
|
2970
|
-
if (isString(lastValue)) {
|
|
2971
|
-
// If the attribute has been provided then we trigger an interpolation to ensure
|
|
2972
|
-
// the value is there for use in the link fn
|
|
2973
|
-
destination[scopeName] = $interpolate(lastValue)(scope);
|
|
2974
|
-
} else if (isBoolean(lastValue)) {
|
|
2975
|
-
// If the attributes is one of the BOOLEAN_ATTR then AngularTS will have converted
|
|
2976
|
-
// the value to boolean rather than a string, so we special case this situation
|
|
2977
|
-
destination[scopeName] = lastValue;
|
|
2978
|
-
}
|
|
2979
|
-
|
|
2980
|
-
/**
|
|
2981
|
-
* @type {SimpleChange}
|
|
2982
|
-
*/
|
|
2983
|
-
initialChanges[scopeName] = {
|
|
2984
|
-
currentValue: destination[scopeName],
|
|
2985
|
-
firstChange: true,
|
|
2986
|
-
};
|
|
2987
|
-
removeWatchCollection.push(removeWatch);
|
|
2988
|
-
break;
|
|
2989
|
-
|
|
2990
|
-
case "=": {
|
|
2991
|
-
if (!hasOwn(attrs, attrName)) {
|
|
2992
|
-
if (optional) {
|
|
2993
|
-
break;
|
|
2994
|
-
}
|
|
2995
|
-
strictBindingsCheck(attrName, directive.name);
|
|
2996
|
-
attrs[attrName] = undefined;
|
|
2997
|
-
}
|
|
2998
|
-
if (optional && !attrs[attrName]) {
|
|
2999
|
-
break;
|
|
3000
|
-
}
|
|
3001
|
-
|
|
3002
|
-
parentGet = $parse(attrs[attrName]);
|
|
3003
|
-
if (parentGet.literal) {
|
|
3004
|
-
compare = equals;
|
|
3005
|
-
} else {
|
|
3006
|
-
compare = simpleCompare;
|
|
3007
|
-
}
|
|
3008
|
-
|
|
3009
|
-
parentSet =
|
|
3010
|
-
parentGet.assign ||
|
|
3011
|
-
function () {
|
|
3012
|
-
// reset the change, or we will throw this exception on every $digest
|
|
3013
|
-
lastValue = destination.$target[scopeName] =
|
|
3014
|
-
parentGet(scope);
|
|
3015
|
-
throw $compileMinErr(
|
|
3016
|
-
"nonassign",
|
|
3017
|
-
"Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!",
|
|
3018
|
-
attrs[attrName],
|
|
3019
|
-
attrName,
|
|
3020
|
-
directive.name,
|
|
3021
|
-
);
|
|
3022
|
-
};
|
|
3023
|
-
// store the value that the parent scope had after the last check:
|
|
3024
|
-
lastValue = destination.$target[scopeName] = parentGet(
|
|
3025
|
-
scope.$target,
|
|
3026
|
-
);
|
|
3027
|
-
const parentValueWatch = function parentValueWatch(
|
|
3028
|
-
parentValue,
|
|
3029
|
-
) {
|
|
3030
|
-
if (!compare(parentValue, destination[scopeName])) {
|
|
3031
|
-
// we are out of sync and need to copy
|
|
3032
|
-
if (!compare(parentValue, lastValue)) {
|
|
3033
|
-
// parent changed and it has precedence
|
|
3034
|
-
destination[scopeName] = parentValue;
|
|
3035
|
-
} else {
|
|
3036
|
-
// if the parent can be assigned then do so
|
|
3037
|
-
parentSet(
|
|
3038
|
-
scope,
|
|
3039
|
-
(parentValue = destination[scopeName]),
|
|
3040
|
-
);
|
|
3041
|
-
}
|
|
3042
|
-
}
|
|
3043
|
-
lastValue = parentValue;
|
|
3044
|
-
return lastValue;
|
|
3045
|
-
};
|
|
3046
|
-
parentValueWatch.$stateful = true;
|
|
3047
|
-
if (definition.collection) {
|
|
3048
|
-
removeWatch = scope.$watch(
|
|
3049
|
-
attrs[attrName],
|
|
3050
|
-
parentValueWatch,
|
|
3051
|
-
);
|
|
3052
|
-
} else {
|
|
3053
|
-
if (attrs[attrName]) {
|
|
3054
|
-
let expr = attrs[attrName];
|
|
3055
|
-
// make it lazy as we dont want to trigger the two way data binding at this point
|
|
3056
|
-
scope.$watch(
|
|
3057
|
-
expr,
|
|
3058
|
-
(val) => {
|
|
3059
|
-
const res = $parse(attrs[attrName], parentValueWatch);
|
|
3060
|
-
if (val) {
|
|
3061
|
-
if (parentGet.literal) {
|
|
3062
|
-
scope.$target[attrName] = val;
|
|
3063
|
-
} else {
|
|
3064
|
-
scope[attrName] = val;
|
|
3065
|
-
}
|
|
3066
|
-
res(scope);
|
|
3067
|
-
} else {
|
|
3068
|
-
scope[attrName] = scope[attrs[attrName]];
|
|
3069
|
-
}
|
|
3070
|
-
},
|
|
3071
|
-
true,
|
|
3072
|
-
);
|
|
3073
|
-
}
|
|
3074
|
-
|
|
3075
|
-
removeWatch = destination.$watch(
|
|
3076
|
-
attrName,
|
|
3077
|
-
(val) => {
|
|
3078
|
-
if (
|
|
3079
|
-
val === lastValue &&
|
|
3080
|
-
!isUndefined(attrs[attrName])
|
|
3081
|
-
) {
|
|
3082
|
-
return;
|
|
3083
|
-
}
|
|
3084
|
-
if (
|
|
3085
|
-
(!!parentGet.inputs && !parentGet.literal) ||
|
|
3086
|
-
(isUndefined(attrs[attrName]) && isDefined(val))
|
|
3087
|
-
) {
|
|
3088
|
-
destination.$target[attrName] = lastValue;
|
|
3089
|
-
throw $compileMinErr(
|
|
3090
|
-
"nonassign",
|
|
3091
|
-
"Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!",
|
|
3092
|
-
attrs[attrName],
|
|
3093
|
-
attrName,
|
|
3094
|
-
directive.name,
|
|
3095
|
-
);
|
|
3096
|
-
} else {
|
|
3097
|
-
// manually set the handler to avoid watch cycles
|
|
3098
|
-
if (isObject(val)) {
|
|
3099
|
-
Object.entries(val).forEach(([key, value]) => {
|
|
3100
|
-
scope.$target[key] = value;
|
|
3101
|
-
});
|
|
3102
|
-
} else {
|
|
3103
|
-
parentSet(scope.$target, (lastValue = val));
|
|
3104
|
-
scope.$handler.watchers
|
|
3105
|
-
.get(attrs[attrName])
|
|
3106
|
-
?.forEach((watchFn) => {
|
|
3107
|
-
watchFn.listenerFn(val);
|
|
3108
|
-
});
|
|
3109
|
-
}
|
|
3110
|
-
}
|
|
3111
|
-
},
|
|
3112
|
-
true,
|
|
3113
|
-
);
|
|
3114
|
-
}
|
|
3115
|
-
removeWatchCollection.push(removeWatch);
|
|
3116
|
-
break;
|
|
3117
|
-
}
|
|
3118
|
-
|
|
3119
|
-
case "<":
|
|
3120
|
-
if (!hasOwn(attrs, attrName)) {
|
|
3121
|
-
if (optional) {
|
|
3122
|
-
break;
|
|
3123
|
-
}
|
|
3124
|
-
strictBindingsCheck(attrName, directive.name);
|
|
3125
|
-
attrs[attrName] = undefined;
|
|
3126
|
-
}
|
|
3127
|
-
if (optional && !attrs[attrName]) {
|
|
3128
|
-
break;
|
|
3129
|
-
}
|
|
3130
|
-
|
|
3131
|
-
parentGet = $parse(attrs[attrName]);
|
|
3132
|
-
|
|
3133
|
-
destination.$target[scopeName] = parentGet(scope.$target);
|
|
3134
|
-
/** @type {SimpleChange} */
|
|
3135
|
-
initialChanges[scopeName] = {
|
|
3136
|
-
currentValue: destination.$target[scopeName],
|
|
3137
|
-
firstChange: firstChange,
|
|
3138
|
-
};
|
|
3139
|
-
scope.$target.attrs = attrs;
|
|
3140
|
-
|
|
3141
|
-
if (attrs[attrName]) {
|
|
3142
|
-
removeWatch = scope.$watch(
|
|
3143
|
-
attrs[attrName],
|
|
3144
|
-
(val) => {
|
|
3145
|
-
destination.$target[scopeName] = val;
|
|
3146
|
-
recordChanges(scopeName, val, firstChange);
|
|
3147
|
-
if (firstChange) {
|
|
3148
|
-
firstChange = false;
|
|
3149
|
-
}
|
|
3150
|
-
},
|
|
3151
|
-
true,
|
|
3152
|
-
);
|
|
3153
|
-
removeWatchCollection.push(removeWatch);
|
|
3154
|
-
}
|
|
3155
|
-
break;
|
|
3156
|
-
|
|
3157
|
-
case "&":
|
|
3158
|
-
if (!optional && !hasOwn(attrs, attrName)) {
|
|
3159
|
-
strictBindingsCheck(attrName, directive.name);
|
|
3160
|
-
}
|
|
3161
|
-
// Don't assign Object.prototype method to scope
|
|
3162
|
-
parentGet = hasOwn(attrs, attrName)
|
|
3163
|
-
? $parse(attrs[attrName])
|
|
3164
|
-
: () => {};
|
|
3165
|
-
|
|
3166
|
-
// Don't assign noop to destination if expression is not valid
|
|
3167
|
-
if (
|
|
3168
|
-
parentGet.toString() === (() => {}).toString() &&
|
|
3169
|
-
optional
|
|
3170
|
-
) {
|
|
3171
|
-
break;
|
|
3172
|
-
}
|
|
3173
|
-
|
|
3174
|
-
destination.$target[scopeName] = function (locals) {
|
|
3175
|
-
return parentGet(scope.$target, locals);
|
|
3176
|
-
};
|
|
3177
|
-
|
|
3178
|
-
break;
|
|
3179
|
-
}
|
|
3180
|
-
});
|
|
3181
|
-
}
|
|
3182
|
-
|
|
3183
|
-
function recordChanges(key, currentValue, initial) {
|
|
3184
|
-
if (isFunction(destination["$onChanges"])) {
|
|
3185
|
-
// If we have not already scheduled the top level onChangesQueue handler then do so now
|
|
3186
|
-
if (!onChangesQueue) {
|
|
3187
|
-
scope.$postUpdate(flushOnChangesQueue);
|
|
3188
|
-
onChangesQueue = [];
|
|
3189
|
-
}
|
|
3190
|
-
// If we have not already queued a trigger of onChanges for this controller then do so now
|
|
3191
|
-
if (!changes) {
|
|
3192
|
-
changes = {};
|
|
3193
|
-
onChangesQueue.push(triggerOnChangesHook);
|
|
3194
|
-
}
|
|
3195
|
-
// Store this change
|
|
3196
|
-
changes[key] = {
|
|
3197
|
-
currentValue: currentValue,
|
|
3198
|
-
firstChange: initial,
|
|
3199
|
-
};
|
|
3200
|
-
}
|
|
3201
|
-
}
|
|
3202
|
-
|
|
3203
|
-
function triggerOnChangesHook() {
|
|
3204
|
-
destination["$onChanges"] &&
|
|
3205
|
-
changes &&
|
|
3206
|
-
destination["$onChanges"](changes);
|
|
3207
|
-
// Now clear the changes so that we schedule onChanges when more changes arrive
|
|
3208
|
-
changes = undefined;
|
|
3209
|
-
}
|
|
3210
|
-
|
|
3211
|
-
return {
|
|
3212
|
-
initialChanges,
|
|
3213
|
-
removeWatches:
|
|
3214
|
-
removeWatchCollection.length &&
|
|
3215
|
-
function removeWatches() {
|
|
3216
|
-
for (
|
|
3217
|
-
let i = 0, ii = removeWatchCollection.length;
|
|
3218
|
-
i < ii;
|
|
3219
|
-
++i
|
|
3220
|
-
) {
|
|
3221
|
-
removeWatchCollection[i]();
|
|
3222
|
-
}
|
|
3223
|
-
},
|
|
3224
|
-
};
|
|
3225
|
-
}
|
|
3226
|
-
},
|
|
3227
|
-
];
|
|
3228
|
-
}
|
|
3229
|
-
}
|
|
3230
|
-
|
|
3231
|
-
function removeComments(jqNodes) {
|
|
3232
|
-
let i = jqNodes.length;
|
|
3233
|
-
|
|
3234
|
-
if (i <= 1) {
|
|
3235
|
-
return jqNodes;
|
|
3236
|
-
}
|
|
3237
|
-
|
|
3238
|
-
while (i--) {
|
|
3239
|
-
const node = jqNodes[i];
|
|
3240
|
-
if (
|
|
3241
|
-
node.nodeType === Node.COMMENT_NODE ||
|
|
3242
|
-
(node.nodeType === Node.TEXT_NODE && node.nodeValue.trim() === "")
|
|
3243
|
-
) {
|
|
3244
|
-
[].splice.call(jqNodes, i, 1);
|
|
3245
|
-
}
|
|
3246
|
-
}
|
|
3247
|
-
return jqNodes;
|
|
3248
|
-
}
|
|
3249
|
-
|
|
3250
|
-
/**
|
|
3251
|
-
* @param {String} name
|
|
3252
|
-
* @returns {void}
|
|
3253
|
-
*/
|
|
3254
|
-
function assertValidDirectiveName(name) {
|
|
3255
|
-
const letter = name.charAt(0);
|
|
3256
|
-
if (!letter || letter !== lowercase(letter)) {
|
|
3257
|
-
throw $compileMinErr(
|
|
3258
|
-
"baddir",
|
|
3259
|
-
"Directive/Component name '{0}' is invalid. The first character must be a lowercase letter",
|
|
3260
|
-
name,
|
|
3261
|
-
);
|
|
3262
|
-
}
|
|
3263
|
-
if (name !== name.trim()) {
|
|
3264
|
-
throw $compileMinErr(
|
|
3265
|
-
"baddir",
|
|
3266
|
-
"Directive/Component name '{0}' is invalid. The name should not contain leading or trailing whitespaces",
|
|
3267
|
-
name,
|
|
3268
|
-
);
|
|
3269
|
-
}
|
|
3270
|
-
}
|