@angular/core 16.0.0-next.3 → 16.0.0-next.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/{esm2020 → esm2022}/src/application_init.mjs +3 -3
- package/{esm2020 → esm2022}/src/application_module.mjs +4 -4
- package/esm2022/src/application_ref.mjs +908 -0
- package/esm2022/src/application_tokens.mjs +105 -0
- package/esm2022/src/change_detection/change_detector_ref.mjs +93 -0
- package/esm2022/src/change_detection/differs/iterable_differs.mjs +81 -0
- package/esm2022/src/change_detection/differs/keyvalue_differs.mjs +74 -0
- package/esm2022/src/compiler/compiler_facade_interface.mjs +29 -0
- package/{esm2020 → esm2022}/src/console.mjs +3 -3
- package/esm2022/src/core.mjs +56 -0
- package/esm2022/src/core_private_export.mjs +39 -0
- package/esm2022/src/core_reactivity_export_internal.mjs +12 -0
- package/esm2022/src/core_render3_private_export.mjs +37 -0
- package/esm2022/src/di/contextual.mjs +54 -0
- package/esm2022/src/di/index.mjs +29 -0
- package/esm2022/src/di/injector.mjs +62 -0
- package/esm2022/src/di/injector_compatibility.mjs +239 -0
- package/esm2022/src/di/provider_collection.mjs +279 -0
- package/esm2022/src/di/r3_injector.mjs +428 -0
- package/esm2022/src/di/reflective_injector.mjs +311 -0
- package/{esm2020 → esm2022}/src/errors.mjs +1 -1
- package/esm2022/src/hydration/annotate.mjs +426 -0
- package/esm2022/src/hydration/api.mjs +143 -0
- package/esm2022/src/hydration/cleanup.mjs +103 -0
- package/esm2022/src/hydration/compression.mjs +69 -0
- package/esm2022/src/hydration/error_handling.mjs +379 -0
- package/esm2022/src/hydration/interfaces.mjs +33 -0
- package/esm2022/src/hydration/node_lookup_utils.mjs +273 -0
- package/esm2022/src/hydration/utils.mjs +219 -0
- package/esm2022/src/hydration/views.mjs +84 -0
- package/esm2022/src/initial_render_pending_tasks.mjs +75 -0
- package/{esm2020 → esm2022}/src/linker/compiler.mjs +5 -5
- package/esm2022/src/linker/component_factory_resolver.mjs +42 -0
- package/esm2022/src/linker/destroy_ref.mjs +44 -0
- package/{esm2020 → esm2022}/src/linker/element_ref.mjs +6 -6
- package/esm2022/src/linker/query_list.mjs +169 -0
- package/{esm2020 → esm2022}/src/linker/template_ref.mjs +6 -6
- package/esm2022/src/linker/view_container_ref.mjs +395 -0
- package/esm2022/src/metadata/di.mjs +69 -0
- package/esm2022/src/metadata/directives.mjs +116 -0
- package/{esm2020 → esm2022}/src/metadata/do_boostrap.mjs +1 -1
- package/{esm2020 → esm2022}/src/metadata/ng_module.mjs +2 -2
- package/esm2022/src/metadata.mjs +18 -0
- package/{esm2020 → esm2022}/src/render/api.mjs +6 -6
- package/esm2022/src/render3/component_ref.mjs +386 -0
- package/{esm2020 → esm2022}/src/render3/context_discovery.mjs +1 -1
- package/esm2022/src/render3/features/standalone_feature.mjs +70 -0
- package/esm2022/src/render3/instructions/element.mjs +205 -0
- package/{esm2020 → esm2022}/src/render3/instructions/element_container.mjs +2 -5
- package/esm2022/src/render3/instructions/element_validation.mjs +271 -0
- package/esm2022/src/render3/instructions/listener.mjs +244 -0
- package/esm2022/src/render3/instructions/mark_view_dirty.mjs +35 -0
- package/esm2022/src/render3/instructions/projection.mjs +121 -0
- package/esm2022/src/render3/instructions/shared.mjs +1681 -0
- package/{esm2020 → esm2022}/src/render3/instructions/styling.mjs +5 -2
- package/esm2022/src/render3/instructions/template.mjs +117 -0
- package/esm2022/src/render3/instructions/text.mjs +67 -0
- package/esm2022/src/render3/interfaces/public_definitions.mjs +9 -0
- package/esm2022/src/render3/interfaces/type_checks.mjs +42 -0
- package/esm2022/src/render3/interfaces/view.mjs +49 -0
- package/esm2022/src/render3/jit/module.mjs +531 -0
- package/esm2022/src/render3/node_manipulation.mjs +960 -0
- package/esm2022/src/render3/node_selector_matcher.mjs +426 -0
- package/esm2022/src/render3/reactive_lview_consumer.mjs +80 -0
- package/esm2022/src/render3/reactivity/effect.mjs +67 -0
- package/{esm2020 → esm2022}/src/render3/util/change_detection_utils.mjs +2 -2
- package/{esm2020 → esm2022}/src/render3/util/view_utils.mjs +12 -1
- package/esm2022/src/render3/view_ref.mjs +307 -0
- package/{esm2020 → esm2022}/src/sanitization/sanitizer.mjs +7 -7
- package/esm2022/src/signals/index.mjs +15 -0
- package/esm2022/src/signals/src/api.mjs +47 -0
- package/esm2022/src/signals/src/computed.mjs +139 -0
- package/esm2022/src/signals/src/graph.mjs +165 -0
- package/esm2022/src/signals/src/signal.mjs +75 -0
- package/esm2022/src/signals/src/watch.mjs +62 -0
- package/esm2022/src/signals/src/weak_ref.mjs +35 -0
- package/{esm2020 → esm2022}/src/testability/testability.mjs +5 -5
- package/esm2022/src/transfer_state.mjs +153 -0
- package/esm2022/src/util/ng_dev_mode.mjs +79 -0
- package/{esm2020 → esm2022}/src/version.mjs +1 -1
- package/{esm2020 → esm2022}/testing/src/logger.mjs +4 -4
- package/{esm2020 → esm2022}/testing/src/ng_zone_mock.mjs +4 -4
- package/{esm2020 → esm2022}/testing/src/test_bed.mjs +2 -2
- package/esm2022/testing/src/test_bed_compiler.mjs +846 -0
- package/{fesm2020 → fesm2022}/core.mjs +1890 -779
- package/fesm2022/core.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/testing.mjs +1203 -178
- package/fesm2022/testing.mjs.map +1 -0
- package/index.d.ts +453 -394
- package/package.json +8 -16
- package/schematics/migrations/guard-and-resolve-interfaces/bundle.js +694 -0
- package/schematics/migrations/guard-and-resolve-interfaces/bundle.js.map +7 -0
- package/schematics/migrations/{router-link-with-href → remove-module-id}/bundle.js +153 -155
- package/schematics/migrations/remove-module-id/bundle.js.map +7 -0
- package/schematics/migrations.json +8 -8
- package/schematics/ng-generate/standalone-migration/bundle.js +1082 -619
- package/schematics/ng-generate/standalone-migration/bundle.js.map +2 -2
- package/testing/index.d.ts +1 -1
- package/esm2020/src/application_ref.mjs +0 -907
- package/esm2020/src/application_tokens.mjs +0 -73
- package/esm2020/src/change_detection/change_detector_ref.mjs +0 -93
- package/esm2020/src/change_detection/differs/iterable_differs.mjs +0 -81
- package/esm2020/src/change_detection/differs/keyvalue_differs.mjs +0 -74
- package/esm2020/src/compiler/compiler_facade_interface.mjs +0 -29
- package/esm2020/src/core.mjs +0 -55
- package/esm2020/src/core_private_export.mjs +0 -37
- package/esm2020/src/core_reactivity_export_internal.mjs +0 -9
- package/esm2020/src/core_render3_private_export.mjs +0 -38
- package/esm2020/src/di/contextual.mjs +0 -37
- package/esm2020/src/di/index.mjs +0 -29
- package/esm2020/src/di/injector.mjs +0 -62
- package/esm2020/src/di/injector_compatibility.mjs +0 -236
- package/esm2020/src/di/provider_collection.mjs +0 -279
- package/esm2020/src/di/r3_injector.mjs +0 -421
- package/esm2020/src/di/reflective_injector.mjs +0 -311
- package/esm2020/src/hydration/annotate.mjs +0 -271
- package/esm2020/src/hydration/api.mjs +0 -128
- package/esm2020/src/hydration/cleanup.mjs +0 -50
- package/esm2020/src/hydration/error_handling.mjs +0 -37
- package/esm2020/src/hydration/interfaces.mjs +0 -17
- package/esm2020/src/hydration/node_lookup_utils.mjs +0 -83
- package/esm2020/src/hydration/utils.mjs +0 -206
- package/esm2020/src/hydration/views.mjs +0 -80
- package/esm2020/src/linker/component_factory_resolver.mjs +0 -42
- package/esm2020/src/linker/destroy_ref.mjs +0 -41
- package/esm2020/src/linker/query_list.mjs +0 -169
- package/esm2020/src/linker/view_container_ref.mjs +0 -394
- package/esm2020/src/metadata/di.mjs +0 -108
- package/esm2020/src/metadata/directives.mjs +0 -111
- package/esm2020/src/metadata.mjs +0 -18
- package/esm2020/src/render3/component_ref.mjs +0 -377
- package/esm2020/src/render3/features/standalone_feature.mjs +0 -70
- package/esm2020/src/render3/instructions/element.mjs +0 -198
- package/esm2020/src/render3/instructions/element_validation.mjs +0 -271
- package/esm2020/src/render3/instructions/listener.mjs +0 -243
- package/esm2020/src/render3/instructions/projection.mjs +0 -118
- package/esm2020/src/render3/instructions/shared.mjs +0 -1696
- package/esm2020/src/render3/instructions/template.mjs +0 -120
- package/esm2020/src/render3/instructions/text.mjs +0 -67
- package/esm2020/src/render3/interfaces/public_definitions.mjs +0 -9
- package/esm2020/src/render3/interfaces/type_checks.mjs +0 -39
- package/esm2020/src/render3/interfaces/view.mjs +0 -47
- package/esm2020/src/render3/jit/module.mjs +0 -544
- package/esm2020/src/render3/node_manipulation.mjs +0 -961
- package/esm2020/src/render3/node_selector_matcher.mjs +0 -414
- package/esm2020/src/render3/view_ref.mjs +0 -306
- package/esm2020/src/signals/index.mjs +0 -15
- package/esm2020/src/signals/src/api.mjs +0 -46
- package/esm2020/src/signals/src/computed.mjs +0 -142
- package/esm2020/src/signals/src/effect.mjs +0 -69
- package/esm2020/src/signals/src/graph.mjs +0 -114
- package/esm2020/src/signals/src/signal.mjs +0 -78
- package/esm2020/src/signals/src/watch.mjs +0 -54
- package/esm2020/src/signals/src/weak_ref.mjs +0 -11
- package/esm2020/src/transfer_state.mjs +0 -153
- package/esm2020/src/util/ng_dev_mode.mjs +0 -78
- package/esm2020/testing/src/test_bed_compiler.mjs +0 -841
- package/fesm2015/core.mjs +0 -29585
- package/fesm2015/core.mjs.map +0 -1
- package/fesm2015/testing.mjs +0 -25669
- package/fesm2015/testing.mjs.map +0 -1
- package/fesm2020/core.mjs.map +0 -1
- package/fesm2020/testing.mjs.map +0 -1
- package/schematics/migrations/relative-link-resolution/bundle.js +0 -283
- package/schematics/migrations/relative-link-resolution/bundle.js.map +0 -7
- package/schematics/migrations/router-link-with-href/bundle.js.map +0 -7
- /package/{esm2020 → esm2022}/core.mjs +0 -0
- /package/{esm2020 → esm2022}/index.mjs +0 -0
- /package/{esm2020 → esm2022}/public_api.mjs +0 -0
- /package/{esm2020 → esm2022}/src/application_config.mjs +0 -0
- /package/{esm2020 → esm2022}/src/change_detection/change_detection.mjs +0 -0
- /package/{esm2020 → esm2022}/src/change_detection/constants.mjs +0 -0
- /package/{esm2020 → esm2022}/src/change_detection/differs/default_iterable_differ.mjs +0 -0
- /package/{esm2020 → esm2022}/src/change_detection/differs/default_keyvalue_differ.mjs +0 -0
- /package/{esm2020 → esm2022}/src/change_detection/pipe_transform.mjs +0 -0
- /package/{esm2020 → esm2022}/src/change_detection.mjs +0 -0
- /package/{esm2020 → esm2022}/src/compiler/compiler_facade.mjs +0 -0
- /package/{esm2020 → esm2022}/src/core_reactivity_export.mjs +0 -0
- /package/{esm2020 → esm2022}/src/debug/debug_node.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/create_injector.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/forward_ref.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/initializer_token.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/inject_switch.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/injectable.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/injection_token.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/injector_marker.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/injector_token.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/interface/defs.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/interface/injector.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/interface/provider.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/internal_tokens.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/jit/environment.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/jit/injectable.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/jit/util.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/metadata.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/metadata_attr.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/null_injector.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/provider_token.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/reflective_errors.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/reflective_key.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/reflective_provider.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di/scope.mjs +0 -0
- /package/{esm2020 → esm2022}/src/di.mjs +0 -0
- /package/{esm2020 → esm2022}/src/error_details_base_url.mjs +0 -0
- /package/{esm2020 → esm2022}/src/error_handler.mjs +0 -0
- /package/{esm2020 → esm2022}/src/event_emitter.mjs +0 -0
- /package/{esm2020 → esm2022}/src/hydration/skip_hydration.mjs +0 -0
- /package/{esm2020 → esm2022}/src/hydration/tokens.mjs +0 -0
- /package/{esm2020 → esm2022}/src/i18n/locale_data_api.mjs +0 -0
- /package/{esm2020 → esm2022}/src/i18n/locale_en.mjs +0 -0
- /package/{esm2020 → esm2022}/src/i18n/localization.mjs +0 -0
- /package/{esm2020 → esm2022}/src/i18n/tokens.mjs +0 -0
- /package/{esm2020 → esm2022}/src/interface/lifecycle_hooks.mjs +0 -0
- /package/{esm2020 → esm2022}/src/interface/simple_change.mjs +0 -0
- /package/{esm2020 → esm2022}/src/interface/type.mjs +0 -0
- /package/{esm2020 → esm2022}/src/linker/component_factory.mjs +0 -0
- /package/{esm2020 → esm2022}/src/linker/ng_module_factory.mjs +0 -0
- /package/{esm2020 → esm2022}/src/linker/ng_module_factory_loader.mjs +0 -0
- /package/{esm2020 → esm2022}/src/linker/ng_module_factory_loader_impl.mjs +0 -0
- /package/{esm2020 → esm2022}/src/linker/ng_module_registration.mjs +0 -0
- /package/{esm2020 → esm2022}/src/linker/view_ref.mjs +0 -0
- /package/{esm2020 → esm2022}/src/linker.mjs +0 -0
- /package/{esm2020 → esm2022}/src/metadata/ng_module_def.mjs +0 -0
- /package/{esm2020 → esm2022}/src/metadata/resource_loading.mjs +0 -0
- /package/{esm2020 → esm2022}/src/metadata/schema.mjs +0 -0
- /package/{esm2020 → esm2022}/src/metadata/view.mjs +0 -0
- /package/{esm2020 → esm2022}/src/platform_core_providers.mjs +0 -0
- /package/{esm2020 → esm2022}/src/r3_symbols.mjs +0 -0
- /package/{esm2020 → esm2022}/src/reflection/platform_reflection_capabilities.mjs +0 -0
- /package/{esm2020 → esm2022}/src/reflection/reflection_capabilities.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render/api_flags.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/assert.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/bindings.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/collect_native_nodes.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/component.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/definition.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/definition_factory.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/di.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/di_setup.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/errors.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/errors_di.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/features/copy_definition_feature.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/features/host_directives_feature.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/features/inherit_definition_feature.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/features/ng_onchanges_feature.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/features/providers_feature.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/fields.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/global_utils_api.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/hooks.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/i18n/i18n_apply.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/i18n/i18n_debug.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/i18n/i18n_insert_before_index.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/i18n/i18n_locale_id.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/i18n/i18n_parse.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/i18n/i18n_postprocess.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/i18n/i18n_tree_shaking.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/i18n/i18n_util.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/index.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/advance.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/all.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/attribute.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/attribute_interpolation.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/change_detection.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/class_map_interpolation.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/di.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/di_attr.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/get_current_view.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/host_property.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/i18n.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/i18n_icu_container_visitor.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/interpolation.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/namespace.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/next_context.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/property.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/property_interpolation.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/storage.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/style_map_interpolation.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/style_prop_interpolation.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/instructions/text_interpolation.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/container.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/context.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/definition.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/document.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/i18n.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/injector.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/lview_tracking.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/node.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/projection.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/query.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/renderer.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/renderer_dom.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/sanitization.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/interfaces/styling.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/jit/directive.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/jit/environment.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/jit/jit_options.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/jit/module_patch.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/jit/partial.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/jit/pipe.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/jit/util.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/metadata.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/namespaces.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/ng_module_ref.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/node_assert.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/node_manipulation_i18n.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/pipe.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/profiler.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/pure_function.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/query.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/state.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/styling/class_differ.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/styling/static_styling.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/styling/style_binding_list.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/styling/styling_parser.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/tokens.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/util/attrs_utils.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/util/discovery_utils.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/util/global_utils.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/util/injector_utils.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/util/misc_utils.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/util/stringify_utils.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/util/view_traversal_utils.mjs +0 -0
- /package/{esm2020 → esm2022}/src/render3/view_engine_compatibility_prebound.mjs +0 -0
- /package/{esm2020 → esm2022}/src/sanitization/bypass.mjs +0 -0
- /package/{esm2020 → esm2022}/src/sanitization/html_sanitizer.mjs +0 -0
- /package/{esm2020 → esm2022}/src/sanitization/iframe_attrs_validation.mjs +0 -0
- /package/{esm2020 → esm2022}/src/sanitization/inert_body.mjs +0 -0
- /package/{esm2020 → esm2022}/src/sanitization/sanitization.mjs +0 -0
- /package/{esm2020 → esm2022}/src/sanitization/security.mjs +0 -0
- /package/{esm2020 → esm2022}/src/sanitization/url_sanitizer.mjs +0 -0
- /package/{esm2020 → esm2022}/src/signals/src/untracked.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/array_utils.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/assert.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/char_code.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/closure.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/coercion.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/comparison.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/decorators.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/dom.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/empty.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/errors.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/global.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/is_dev_mode.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/iterable.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/lang.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/microtask.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/ng_i18n_closure_mode.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/ng_jit_mode.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/ng_reflect.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/noop.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/property.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/raf.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/security/trusted_type_defs.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/security/trusted_types.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/security/trusted_types_bypass.mjs +0 -0
- /package/{esm2020 → esm2022}/src/util/stringify.mjs +0 -0
- /package/{esm2020 → esm2022}/src/view/provider_flags.mjs +0 -0
- /package/{esm2020 → esm2022}/src/zone/async-stack-tagging.mjs +0 -0
- /package/{esm2020 → esm2022}/src/zone/ng_zone.mjs +0 -0
- /package/{esm2020 → esm2022}/src/zone.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/index.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/public_api.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/async.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/component_fixture.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/fake_async.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/metadata_override.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/metadata_overrider.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/resolvers.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/styling.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/test_bed_common.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/test_hooks.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/testing.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/testing_internal.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/testing.mjs +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v16.0.0-next.
|
|
2
|
+
* @license Angular v16.0.0-next.5
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { getDebugNode, RendererFactory2 as RendererFactory2$1, InjectionToken as InjectionToken$1, ɵstringify, ɵReflectionCapabilities, Directive, Component, Pipe, NgModule, ɵgetInjectableDef, resolveForwardRef as resolveForwardRef$1, ɵNG_COMP_DEF, ɵRender3NgModuleRef, ApplicationInitStatus, LOCALE_ID as LOCALE_ID$1, ɵDEFAULT_LOCALE_ID, ɵsetLocaleId, ɵRender3ComponentFactory, ɵcompileComponent, ɵNG_DIR_DEF, ɵcompileDirective, ɵNG_PIPE_DEF, ɵcompilePipe, ɵNG_MOD_DEF, ɵtransitiveScopesFor, ɵpatchComponentDefWithScope, ɵNG_INJ_DEF, ɵcompileNgModuleDefs, NgZone, ɵprovideNgZoneChangeDetection, Compiler, COMPILER_OPTIONS, ɵNgModuleFactory, ɵisEnvironmentProviders, ModuleWithComponentFactories, ɵconvertToBitFlags, Injector as Injector$1, InjectFlags as InjectFlags$1, ɵsetAllowDuplicateNgModuleIdsForTest, ɵresetCompiledComponents, ɵsetUnknownElementStrictMode as ɵsetUnknownElementStrictMode$1, ɵsetUnknownPropertyStrictMode as ɵsetUnknownPropertyStrictMode$1, ɵgetUnknownElementStrictMode as ɵgetUnknownElementStrictMode$1, ɵgetUnknownPropertyStrictMode as ɵgetUnknownPropertyStrictMode$1, EnvironmentInjector as EnvironmentInjector$1, ɵflushModuleScopingQueueAsMuchAsPossible } from '@angular/core';
|
|
8
8
|
import { ResourceLoader } from '@angular/compiler';
|
|
9
9
|
import { Subject, Subscription } from 'rxjs';
|
|
10
|
+
import { first } from 'rxjs/operators';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Wraps a test function in an asynchronous test zone. The test will automatically
|
|
@@ -1638,6 +1639,7 @@ function ngDevModeResetPerfCounters() {
|
|
|
1638
1639
|
hydratedNodes: 0,
|
|
1639
1640
|
hydratedComponents: 0,
|
|
1640
1641
|
dehydratedViewsRemoved: 0,
|
|
1642
|
+
dehydratedViewsCleanupRuns: 0,
|
|
1641
1643
|
};
|
|
1642
1644
|
// Make sure to refer to ngDevMode as ['ngDevMode'] for closure.
|
|
1643
1645
|
const allowNgDevModeTrue = locationString.indexOf('ngDevMode=false') === -1;
|
|
@@ -1840,6 +1842,9 @@ const SOURCE = '__source';
|
|
|
1840
1842
|
* - Injector instance: Use the injector for resolution.
|
|
1841
1843
|
*/
|
|
1842
1844
|
let _currentInjector = undefined;
|
|
1845
|
+
function getCurrentInjector() {
|
|
1846
|
+
return _currentInjector;
|
|
1847
|
+
}
|
|
1843
1848
|
function setCurrentInjector(injector) {
|
|
1844
1849
|
const former = _currentInjector;
|
|
1845
1850
|
_currentInjector = injector;
|
|
@@ -1848,7 +1853,7 @@ function setCurrentInjector(injector) {
|
|
|
1848
1853
|
function injectInjectorOnly(token, flags = InjectFlags.Default) {
|
|
1849
1854
|
if (_currentInjector === undefined) {
|
|
1850
1855
|
throw new RuntimeError(-203 /* RuntimeErrorCode.MISSING_INJECTION_CONTEXT */, ngDevMode &&
|
|
1851
|
-
`inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with \`
|
|
1856
|
+
`inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with \`runInInjectionContext\`.`);
|
|
1852
1857
|
}
|
|
1853
1858
|
else if (_currentInjector === null) {
|
|
1854
1859
|
return injectRootLimpMode(token, undefined, flags);
|
|
@@ -2446,12 +2451,19 @@ function isCssClassMatching(attrs, cssClassToMatch, isProjectionMode) {
|
|
|
2446
2451
|
ngDevMode &&
|
|
2447
2452
|
assertEqual(cssClassToMatch, cssClassToMatch.toLowerCase(), 'Class name expected to be lowercase.');
|
|
2448
2453
|
let i = 0;
|
|
2454
|
+
// Indicates whether we are processing value from the implicit
|
|
2455
|
+
// attribute section (i.e. before the first marker in the array).
|
|
2456
|
+
let isImplicitAttrsSection = true;
|
|
2449
2457
|
while (i < attrs.length) {
|
|
2450
2458
|
let item = attrs[i++];
|
|
2451
|
-
if (
|
|
2452
|
-
|
|
2453
|
-
if (
|
|
2454
|
-
|
|
2459
|
+
if (typeof item === 'string' && isImplicitAttrsSection) {
|
|
2460
|
+
const value = attrs[i++];
|
|
2461
|
+
if (isProjectionMode && item === 'class') {
|
|
2462
|
+
// We found a `class` attribute in the implicit attribute section,
|
|
2463
|
+
// check if it matches the value of the `cssClassToMatch` argument.
|
|
2464
|
+
if (classIndexOf(value.toLowerCase(), cssClassToMatch, 0) !== -1) {
|
|
2465
|
+
return true;
|
|
2466
|
+
}
|
|
2455
2467
|
}
|
|
2456
2468
|
}
|
|
2457
2469
|
else if (item === 1 /* AttributeMarker.Classes */) {
|
|
@@ -2463,6 +2475,11 @@ function isCssClassMatching(attrs, cssClassToMatch, isProjectionMode) {
|
|
|
2463
2475
|
}
|
|
2464
2476
|
return false;
|
|
2465
2477
|
}
|
|
2478
|
+
else if (typeof item === 'number') {
|
|
2479
|
+
// We've came across a first marker, which indicates
|
|
2480
|
+
// that the implicit attribute section is over.
|
|
2481
|
+
isImplicitAttrsSection = false;
|
|
2482
|
+
}
|
|
2466
2483
|
}
|
|
2467
2484
|
return false;
|
|
2468
2485
|
}
|
|
@@ -3217,6 +3234,8 @@ const ID = 20;
|
|
|
3217
3234
|
const EMBEDDED_VIEW_INJECTOR = 21;
|
|
3218
3235
|
const ON_DESTROY_HOOKS = 22;
|
|
3219
3236
|
const HYDRATION = 23;
|
|
3237
|
+
const REACTIVE_TEMPLATE_CONSUMER = 24;
|
|
3238
|
+
const REACTIVE_HOST_BINDING_CONSUMER = 25;
|
|
3220
3239
|
/**
|
|
3221
3240
|
* Size of LView's header. Necessary to adjust for it when setting slots.
|
|
3222
3241
|
*
|
|
@@ -3224,7 +3243,7 @@ const HYDRATION = 23;
|
|
|
3224
3243
|
* instruction index into `LView` index. All other indexes should be in the `LView` index space and
|
|
3225
3244
|
* there should be no need to refer to `HEADER_OFFSET` anywhere else.
|
|
3226
3245
|
*/
|
|
3227
|
-
const HEADER_OFFSET =
|
|
3246
|
+
const HEADER_OFFSET = 26;
|
|
3228
3247
|
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
|
3229
3248
|
// failure based on types.
|
|
3230
3249
|
const unusedValueExportToPlacateAjd$4 = 1;
|
|
@@ -3297,6 +3316,9 @@ function isComponentDef(def) {
|
|
|
3297
3316
|
function isRootView(target) {
|
|
3298
3317
|
return (target[FLAGS] & 256 /* LViewFlags.IsRoot */) !== 0;
|
|
3299
3318
|
}
|
|
3319
|
+
function isProjectionTNode(tNode) {
|
|
3320
|
+
return (tNode.type & 16 /* TNodeType.Projection */) === 16 /* TNodeType.Projection */;
|
|
3321
|
+
}
|
|
3300
3322
|
|
|
3301
3323
|
// [Assert functions do not constraint type when they are guarded by a truthy
|
|
3302
3324
|
// expression.](https://github.com/microsoft/TypeScript/issues/37295)
|
|
@@ -3710,6 +3732,17 @@ function storeLViewOnDestroy(lView, onDestroyCallback) {
|
|
|
3710
3732
|
}
|
|
3711
3733
|
lView[ON_DESTROY_HOOKS].push(onDestroyCallback);
|
|
3712
3734
|
}
|
|
3735
|
+
/**
|
|
3736
|
+
* Removes previously registered LView-specific destroy callback.
|
|
3737
|
+
*/
|
|
3738
|
+
function removeLViewOnDestroy(lView, onDestroyCallback) {
|
|
3739
|
+
if (lView[ON_DESTROY_HOOKS] === null)
|
|
3740
|
+
return;
|
|
3741
|
+
const destroyCBIdx = lView[ON_DESTROY_HOOKS].indexOf(onDestroyCallback);
|
|
3742
|
+
if (destroyCBIdx !== -1) {
|
|
3743
|
+
lView[ON_DESTROY_HOOKS].splice(destroyCBIdx, 1);
|
|
3744
|
+
}
|
|
3745
|
+
}
|
|
3713
3746
|
|
|
3714
3747
|
const instructionState = {
|
|
3715
3748
|
lFrame: createLFrame(null),
|
|
@@ -6711,6 +6744,8 @@ function detachView(lContainer, removeIndex) {
|
|
|
6711
6744
|
function destroyLView(tView, lView) {
|
|
6712
6745
|
if (!(lView[FLAGS] & 128 /* LViewFlags.Destroyed */)) {
|
|
6713
6746
|
const renderer = lView[RENDERER];
|
|
6747
|
+
lView[REACTIVE_TEMPLATE_CONSUMER]?.destroy();
|
|
6748
|
+
lView[REACTIVE_HOST_BINDING_CONSUMER]?.destroy();
|
|
6714
6749
|
if (renderer.destroyNode) {
|
|
6715
6750
|
applyView(tView, lView, renderer, 3 /* WalkTNodeTreeAction.Destroy */, null, null);
|
|
6716
6751
|
}
|
|
@@ -7111,15 +7146,12 @@ function nativeRemoveNode(renderer, rNode, isHostElement) {
|
|
|
7111
7146
|
}
|
|
7112
7147
|
}
|
|
7113
7148
|
/**
|
|
7114
|
-
*
|
|
7149
|
+
* Clears the contents of a given RElement.
|
|
7115
7150
|
*
|
|
7116
|
-
* @param renderer A renderer to be used
|
|
7117
7151
|
* @param rElement the native RElement to be cleared
|
|
7118
7152
|
*/
|
|
7119
|
-
function clearElementContents(
|
|
7120
|
-
|
|
7121
|
-
nativeRemoveChild(renderer, rElement, rElement.firstChild, false);
|
|
7122
|
-
}
|
|
7153
|
+
function clearElementContents(rElement) {
|
|
7154
|
+
rElement.textContent = '';
|
|
7123
7155
|
}
|
|
7124
7156
|
/**
|
|
7125
7157
|
* Performs the operation of `action` on the node. Typically this involves inserting or removing
|
|
@@ -8512,7 +8544,7 @@ function internalImportProvidersFrom(checkForStandaloneCmp, ...sources) {
|
|
|
8512
8544
|
// Narrow `source` to access the internal type analogue for `ModuleWithProviders`.
|
|
8513
8545
|
const internalSource = source;
|
|
8514
8546
|
if (walkProviderTree(internalSource, providersOut, [], dedup)) {
|
|
8515
|
-
injectorTypesWithProviders
|
|
8547
|
+
injectorTypesWithProviders ||= [];
|
|
8516
8548
|
injectorTypesWithProviders.push(internalSource);
|
|
8517
8549
|
}
|
|
8518
8550
|
});
|
|
@@ -8608,7 +8640,7 @@ function walkProviderTree(container, providersOut, parents, dedup) {
|
|
|
8608
8640
|
try {
|
|
8609
8641
|
deepForEach(injDef.imports, imported => {
|
|
8610
8642
|
if (walkProviderTree(imported, providersOut, parents, dedup)) {
|
|
8611
|
-
importTypesWithProviders
|
|
8643
|
+
importTypesWithProviders ||= [];
|
|
8612
8644
|
// If the processed import is an injector type with providers, we store it in the
|
|
8613
8645
|
// list of import types with providers, so that we can process those afterwards.
|
|
8614
8646
|
importTypesWithProviders.push(imported);
|
|
@@ -8805,6 +8837,7 @@ class R3Injector extends EnvironmentInjector {
|
|
|
8805
8837
|
}
|
|
8806
8838
|
onDestroy(callback) {
|
|
8807
8839
|
this._onDestroyHooks.push(callback);
|
|
8840
|
+
return () => this.removeOnDestroy(callback);
|
|
8808
8841
|
}
|
|
8809
8842
|
runInContext(fn) {
|
|
8810
8843
|
this.assertNotDestroyed();
|
|
@@ -8979,6 +9012,12 @@ class R3Injector extends EnvironmentInjector {
|
|
|
8979
9012
|
return this.injectorDefTypes.has(providedIn);
|
|
8980
9013
|
}
|
|
8981
9014
|
}
|
|
9015
|
+
removeOnDestroy(callback) {
|
|
9016
|
+
const destroyCBIdx = this._onDestroyHooks.indexOf(callback);
|
|
9017
|
+
if (destroyCBIdx !== -1) {
|
|
9018
|
+
this._onDestroyHooks.splice(destroyCBIdx, 1);
|
|
9019
|
+
}
|
|
9020
|
+
}
|
|
8982
9021
|
}
|
|
8983
9022
|
function injectableDefOrInjectorDefFactory(token) {
|
|
8984
9023
|
// Most tokens will have an injectable def directly on them, which specifies a factory directly.
|
|
@@ -9164,6 +9203,37 @@ const PACKAGE_ROOT_URL = new InjectionToken('Application Packages Root URL');
|
|
|
9164
9203
|
* @publicApi
|
|
9165
9204
|
*/
|
|
9166
9205
|
const ANIMATION_MODULE_TYPE = new InjectionToken('AnimationModuleType');
|
|
9206
|
+
// TODO(crisbeto): link to CSP guide here.
|
|
9207
|
+
/**
|
|
9208
|
+
* Token used to configure the [Content Security Policy](https://web.dev/strict-csp/) nonce that
|
|
9209
|
+
* Angular will apply when inserting inline styles. If not provided, Angular will look up its value
|
|
9210
|
+
* from the `ngCspNonce` attribute of the application root node.
|
|
9211
|
+
*
|
|
9212
|
+
* @publicApi
|
|
9213
|
+
*/
|
|
9214
|
+
const CSP_NONCE = new InjectionToken('CSP nonce', {
|
|
9215
|
+
providedIn: 'root',
|
|
9216
|
+
factory: () => {
|
|
9217
|
+
// Ideally we wouldn't have to use `querySelector` here since we know that the nonce will be on
|
|
9218
|
+
// the root node, but because the token value is used in renderers, it has to be available
|
|
9219
|
+
// *very* early in the bootstrapping process. This should be a fairly shallow search, because
|
|
9220
|
+
// the app won't have been added to the DOM yet. Some approaches that were considered:
|
|
9221
|
+
// 1. Find the root node through `ApplicationRef.components[i].location` - normally this would
|
|
9222
|
+
// be enough for our purposes, but the token is injected very early so the `components` array
|
|
9223
|
+
// isn't populated yet.
|
|
9224
|
+
// 2. Find the root `LView` through the current `LView` - renderers are a prerequisite to
|
|
9225
|
+
// creating the `LView`. This means that no `LView` will have been entered when this factory is
|
|
9226
|
+
// invoked for the root component.
|
|
9227
|
+
// 3. Have the token factory return `() => string` which is invoked when a nonce is requested -
|
|
9228
|
+
// the slightly later execution does allow us to get an `LView` reference, but the fact that
|
|
9229
|
+
// it is a function means that it could be executed at *any* time (including immediately) which
|
|
9230
|
+
// may lead to weird bugs.
|
|
9231
|
+
// 4. Have the `ComponentFactory` read the attribute and provide it to the injector under the
|
|
9232
|
+
// hood - has the same problem as #1 and #2 in that the renderer is used to query for the root
|
|
9233
|
+
// node and the nonce value needs to be available when the renderer is created.
|
|
9234
|
+
return getDocument().body.querySelector('[ngCspNonce]')?.getAttribute('ngCspNonce') || null;
|
|
9235
|
+
},
|
|
9236
|
+
});
|
|
9167
9237
|
|
|
9168
9238
|
function escapeTransferStateContent(text) {
|
|
9169
9239
|
const escapedText = {
|
|
@@ -9228,6 +9298,13 @@ class TransferState {
|
|
|
9228
9298
|
this.store = {};
|
|
9229
9299
|
this.onSerializeCallbacks = {};
|
|
9230
9300
|
}
|
|
9301
|
+
/** @nocollapse */
|
|
9302
|
+
static { this.ɵprov =
|
|
9303
|
+
/** @pureOrBreakMyCode */ ɵɵdefineInjectable({
|
|
9304
|
+
token: TransferState,
|
|
9305
|
+
providedIn: 'root',
|
|
9306
|
+
factory: initTransferState,
|
|
9307
|
+
}); }
|
|
9231
9308
|
/**
|
|
9232
9309
|
* Get the value corresponding to a key. Return `defaultValue` if key is not found.
|
|
9233
9310
|
*/
|
|
@@ -9282,13 +9359,6 @@ class TransferState {
|
|
|
9282
9359
|
return JSON.stringify(this.store);
|
|
9283
9360
|
}
|
|
9284
9361
|
}
|
|
9285
|
-
/** @nocollapse */
|
|
9286
|
-
TransferState.ɵprov =
|
|
9287
|
-
/** @pureOrBreakMyCode */ ɵɵdefineInjectable({
|
|
9288
|
-
token: TransferState,
|
|
9289
|
-
providedIn: 'root',
|
|
9290
|
-
factory: initTransferState,
|
|
9291
|
-
});
|
|
9292
9362
|
function retrieveTransferredState(doc, appId) {
|
|
9293
9363
|
// Locate the script tag with the JSON data transferred from the server.
|
|
9294
9364
|
// The id of the script tag is set to the Angular appId + 'state'.
|
|
@@ -9306,6 +9376,19 @@ function retrieveTransferredState(doc, appId) {
|
|
|
9306
9376
|
return initialState;
|
|
9307
9377
|
}
|
|
9308
9378
|
|
|
9379
|
+
/** Encodes that the node lookup should start from the host node of this component. */
|
|
9380
|
+
const REFERENCE_NODE_HOST = 'h';
|
|
9381
|
+
/** Encodes that the node lookup should start from the document body node. */
|
|
9382
|
+
const REFERENCE_NODE_BODY = 'b';
|
|
9383
|
+
/**
|
|
9384
|
+
* Describes navigation steps that the runtime logic need to perform,
|
|
9385
|
+
* starting from a given (known) element.
|
|
9386
|
+
*/
|
|
9387
|
+
var NodeNavigationStep;
|
|
9388
|
+
(function (NodeNavigationStep) {
|
|
9389
|
+
NodeNavigationStep["FirstChild"] = "f";
|
|
9390
|
+
NodeNavigationStep["NextSibling"] = "n";
|
|
9391
|
+
})(NodeNavigationStep || (NodeNavigationStep = {}));
|
|
9309
9392
|
/**
|
|
9310
9393
|
* Keys within serialized view data structure to represent various
|
|
9311
9394
|
* parts. See the `SerializedView` interface below for additional information.
|
|
@@ -9313,8 +9396,11 @@ function retrieveTransferredState(doc, appId) {
|
|
|
9313
9396
|
const ELEMENT_CONTAINERS = 'e';
|
|
9314
9397
|
const TEMPLATES = 't';
|
|
9315
9398
|
const CONTAINERS = 'c';
|
|
9399
|
+
const MULTIPLIER = 'x';
|
|
9316
9400
|
const NUM_ROOT_NODES = 'r';
|
|
9317
9401
|
const TEMPLATE_ID = 'i'; // as it's also an "id"
|
|
9402
|
+
const NODES = 'n';
|
|
9403
|
+
const DISCONNECTED_NODES = 'd';
|
|
9318
9404
|
|
|
9319
9405
|
/**
|
|
9320
9406
|
* The name of the key used in the TransferState collection,
|
|
@@ -9468,7 +9554,7 @@ function isRNodeClaimedForHydration(node) {
|
|
|
9468
9554
|
return !!node.__claimed;
|
|
9469
9555
|
}
|
|
9470
9556
|
function setSegmentHead(hydrationInfo, index, node) {
|
|
9471
|
-
hydrationInfo.segmentHeads
|
|
9557
|
+
hydrationInfo.segmentHeads ??= {};
|
|
9472
9558
|
hydrationInfo.segmentHeads[index] = node;
|
|
9473
9559
|
}
|
|
9474
9560
|
function getSegmentHead(hydrationInfo, index) {
|
|
@@ -9504,10 +9590,23 @@ function calcSerializedContainerSize(hydrationInfo, index) {
|
|
|
9504
9590
|
const views = getSerializedContainerViews(hydrationInfo, index) ?? [];
|
|
9505
9591
|
let numNodes = 0;
|
|
9506
9592
|
for (let view of views) {
|
|
9507
|
-
numNodes += view[NUM_ROOT_NODES];
|
|
9593
|
+
numNodes += view[NUM_ROOT_NODES] * (view[MULTIPLIER] ?? 1);
|
|
9508
9594
|
}
|
|
9509
9595
|
return numNodes;
|
|
9510
9596
|
}
|
|
9597
|
+
/**
|
|
9598
|
+
* Checks whether a node is annotated as "disconnected", i.e. not present
|
|
9599
|
+
* in the DOM at serialization time. We should not attempt hydration for
|
|
9600
|
+
* such nodes and instead, use a regular "creation mode".
|
|
9601
|
+
*/
|
|
9602
|
+
function isDisconnectedNode(hydrationInfo, index) {
|
|
9603
|
+
// Check if we are processing disconnected info for the first time.
|
|
9604
|
+
if (typeof hydrationInfo.disconnectedNodes === 'undefined') {
|
|
9605
|
+
const nodeIds = hydrationInfo.data[DISCONNECTED_NODES];
|
|
9606
|
+
hydrationInfo.disconnectedNodes = nodeIds ? (new Set(nodeIds)) : null;
|
|
9607
|
+
}
|
|
9608
|
+
return !!hydrationInfo.disconnectedNodes?.has(index);
|
|
9609
|
+
}
|
|
9511
9610
|
|
|
9512
9611
|
/**
|
|
9513
9612
|
* Represents a component created by a `ComponentFactory`.
|
|
@@ -9534,7 +9633,7 @@ class ComponentFactory$1 {
|
|
|
9534
9633
|
}
|
|
9535
9634
|
|
|
9536
9635
|
function noComponentFactoryError(component) {
|
|
9537
|
-
const error = Error(`No component factory found for ${stringify(component)}
|
|
9636
|
+
const error = Error(`No component factory found for ${stringify(component)}.`);
|
|
9538
9637
|
error[ERROR_COMPONENT] = component;
|
|
9539
9638
|
return error;
|
|
9540
9639
|
}
|
|
@@ -9563,8 +9662,8 @@ class _NullComponentFactoryResolver {
|
|
|
9563
9662
|
* Component class can be used directly.
|
|
9564
9663
|
*/
|
|
9565
9664
|
class ComponentFactoryResolver$1 {
|
|
9665
|
+
static { this.NULL = ( /* @__PURE__ */new _NullComponentFactoryResolver()); }
|
|
9566
9666
|
}
|
|
9567
|
-
ComponentFactoryResolver$1.NULL = ( /* @__PURE__ */new _NullComponentFactoryResolver());
|
|
9568
9667
|
|
|
9569
9668
|
/**
|
|
9570
9669
|
* Creates an ElementRef from the most recent node.
|
|
@@ -9603,12 +9702,12 @@ class ElementRef {
|
|
|
9603
9702
|
constructor(nativeElement) {
|
|
9604
9703
|
this.nativeElement = nativeElement;
|
|
9605
9704
|
}
|
|
9705
|
+
/**
|
|
9706
|
+
* @internal
|
|
9707
|
+
* @nocollapse
|
|
9708
|
+
*/
|
|
9709
|
+
static { this.__NG_ELEMENT_ID__ = injectElementRef; }
|
|
9606
9710
|
}
|
|
9607
|
-
/**
|
|
9608
|
-
* @internal
|
|
9609
|
-
* @nocollapse
|
|
9610
|
-
*/
|
|
9611
|
-
ElementRef.__NG_ELEMENT_ID__ = injectElementRef;
|
|
9612
9711
|
/**
|
|
9613
9712
|
* Unwraps `ElementRef` and return the `nativeElement`.
|
|
9614
9713
|
*
|
|
@@ -9642,12 +9741,12 @@ class RendererFactory2 {
|
|
|
9642
9741
|
* @publicApi
|
|
9643
9742
|
*/
|
|
9644
9743
|
class Renderer2 {
|
|
9744
|
+
/**
|
|
9745
|
+
* @internal
|
|
9746
|
+
* @nocollapse
|
|
9747
|
+
*/
|
|
9748
|
+
static { this.__NG_ELEMENT_ID__ = () => injectRenderer2(); }
|
|
9645
9749
|
}
|
|
9646
|
-
/**
|
|
9647
|
-
* @internal
|
|
9648
|
-
* @nocollapse
|
|
9649
|
-
*/
|
|
9650
|
-
Renderer2.__NG_ELEMENT_ID__ = () => injectRenderer2();
|
|
9651
9750
|
/** Injects a Renderer2 for the current component. */
|
|
9652
9751
|
function injectRenderer2() {
|
|
9653
9752
|
// We need the Renderer to be based on the component that it's being injected into, however since
|
|
@@ -9664,13 +9763,13 @@ function injectRenderer2() {
|
|
|
9664
9763
|
* @publicApi
|
|
9665
9764
|
*/
|
|
9666
9765
|
class Sanitizer {
|
|
9766
|
+
/** @nocollapse */
|
|
9767
|
+
static { this.ɵprov = ɵɵdefineInjectable({
|
|
9768
|
+
token: Sanitizer,
|
|
9769
|
+
providedIn: 'root',
|
|
9770
|
+
factory: () => null,
|
|
9771
|
+
}); }
|
|
9667
9772
|
}
|
|
9668
|
-
/** @nocollapse */
|
|
9669
|
-
Sanitizer.ɵprov = ɵɵdefineInjectable({
|
|
9670
|
-
token: Sanitizer,
|
|
9671
|
-
providedIn: 'root',
|
|
9672
|
-
factory: () => null,
|
|
9673
|
-
});
|
|
9674
9773
|
|
|
9675
9774
|
/**
|
|
9676
9775
|
* @description Represents the version of Angular
|
|
@@ -9688,7 +9787,7 @@ class Version {
|
|
|
9688
9787
|
/**
|
|
9689
9788
|
* @publicApi
|
|
9690
9789
|
*/
|
|
9691
|
-
const VERSION = new Version('16.0.0-next.
|
|
9790
|
+
const VERSION = new Version('16.0.0-next.5');
|
|
9692
9791
|
|
|
9693
9792
|
// This default value is when checking the hierarchy for a token.
|
|
9694
9793
|
//
|
|
@@ -9769,11 +9868,11 @@ class ErrorHandler {
|
|
|
9769
9868
|
}
|
|
9770
9869
|
}
|
|
9771
9870
|
|
|
9772
|
-
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
9871
|
+
const NG_DEV_MODE$1 = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
9773
9872
|
/**
|
|
9774
9873
|
* Internal token that specifies whether hydration is enabled.
|
|
9775
9874
|
*/
|
|
9776
|
-
const IS_HYDRATION_FEATURE_ENABLED = new InjectionToken(NG_DEV_MODE ? 'IS_HYDRATION_FEATURE_ENABLED' : '');
|
|
9875
|
+
const IS_HYDRATION_FEATURE_ENABLED = new InjectionToken(NG_DEV_MODE$1 ? 'IS_HYDRATION_FEATURE_ENABLED' : '');
|
|
9777
9876
|
// By default (in client rendering mode), we remove all the contents
|
|
9778
9877
|
// of the host element and render an application after that.
|
|
9779
9878
|
const PRESERVE_HOST_CONTENT_DEFAULT = false;
|
|
@@ -9781,7 +9880,7 @@ const PRESERVE_HOST_CONTENT_DEFAULT = false;
|
|
|
9781
9880
|
* Internal token that indicates whether host element content should be
|
|
9782
9881
|
* retained during the bootstrap.
|
|
9783
9882
|
*/
|
|
9784
|
-
const PRESERVE_HOST_CONTENT = new InjectionToken(NG_DEV_MODE ? 'PRESERVE_HOST_CONTENT' : '', {
|
|
9883
|
+
const PRESERVE_HOST_CONTENT = new InjectionToken(NG_DEV_MODE$1 ? 'PRESERVE_HOST_CONTENT' : '', {
|
|
9785
9884
|
providedIn: 'root',
|
|
9786
9885
|
factory: () => PRESERVE_HOST_CONTENT_DEFAULT,
|
|
9787
9886
|
});
|
|
@@ -9891,6 +9990,285 @@ function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValu
|
|
|
9891
9990
|
return { propName: undefined, oldValue, newValue };
|
|
9892
9991
|
}
|
|
9893
9992
|
|
|
9993
|
+
/**
|
|
9994
|
+
* A `WeakRef`-compatible reference that fakes the API with a strong reference
|
|
9995
|
+
* internally.
|
|
9996
|
+
*/
|
|
9997
|
+
class LeakyRef {
|
|
9998
|
+
constructor(ref) {
|
|
9999
|
+
this.ref = ref;
|
|
10000
|
+
}
|
|
10001
|
+
deref() {
|
|
10002
|
+
return this.ref;
|
|
10003
|
+
}
|
|
10004
|
+
}
|
|
10005
|
+
// `WeakRef` is not always defined in every TS environment where Angular is compiled. Instead,
|
|
10006
|
+
// read it off of the global context if available.
|
|
10007
|
+
// tslint:disable-next-line: no-toplevel-property-access
|
|
10008
|
+
let WeakRefImpl = _global$1['WeakRef'] ?? LeakyRef;
|
|
10009
|
+
function newWeakRef(value) {
|
|
10010
|
+
if (typeof ngDevMode !== 'undefined' && ngDevMode && WeakRefImpl === undefined) {
|
|
10011
|
+
throw new Error(`Angular requires a browser which supports the 'WeakRef' API`);
|
|
10012
|
+
}
|
|
10013
|
+
return new WeakRefImpl(value);
|
|
10014
|
+
}
|
|
10015
|
+
function setAlternateWeakRefImpl(impl) {
|
|
10016
|
+
// no-op since the alternate impl is included by default by the framework. Remove once internal
|
|
10017
|
+
// migration is complete.
|
|
10018
|
+
}
|
|
10019
|
+
|
|
10020
|
+
/**
|
|
10021
|
+
* Counter tracking the next `ProducerId` or `ConsumerId`.
|
|
10022
|
+
*/
|
|
10023
|
+
let _nextReactiveId = 0;
|
|
10024
|
+
/**
|
|
10025
|
+
* Tracks the currently active reactive consumer (or `null` if there is no active
|
|
10026
|
+
* consumer).
|
|
10027
|
+
*/
|
|
10028
|
+
let activeConsumer = null;
|
|
10029
|
+
function setActiveConsumer(consumer) {
|
|
10030
|
+
const prev = activeConsumer;
|
|
10031
|
+
activeConsumer = consumer;
|
|
10032
|
+
return prev;
|
|
10033
|
+
}
|
|
10034
|
+
/**
|
|
10035
|
+
* A node in the reactive graph.
|
|
10036
|
+
*
|
|
10037
|
+
* Nodes can be producers of reactive values, consumers of other reactive values, or both.
|
|
10038
|
+
*
|
|
10039
|
+
* Producers are nodes that produce values, and can be depended upon by consumer nodes.
|
|
10040
|
+
*
|
|
10041
|
+
* Producers expose a monotonic `valueVersion` counter, and are responsible for incrementing this
|
|
10042
|
+
* version when their value semantically changes. Some producers may produce their values lazily and
|
|
10043
|
+
* thus at times need to be polled for potential updates to their value (and by extension their
|
|
10044
|
+
* `valueVersion`). This is accomplished via the `onProducerUpdateValueVersion` method for
|
|
10045
|
+
* implemented by producers, which should perform whatever calculations are necessary to ensure
|
|
10046
|
+
* `valueVersion` is up to date.
|
|
10047
|
+
*
|
|
10048
|
+
* Consumers are nodes that depend on the values of producers and are notified when those values
|
|
10049
|
+
* might have changed.
|
|
10050
|
+
*
|
|
10051
|
+
* Consumers do not wrap the reads they consume themselves, but rather can be set as the active
|
|
10052
|
+
* reader via `setActiveConsumer`. Reads of producers that happen while a consumer is active will
|
|
10053
|
+
* result in those producers being added as dependencies of that consumer node.
|
|
10054
|
+
*
|
|
10055
|
+
* The set of dependencies of a consumer is dynamic. Implementers expose a monotonically increasing
|
|
10056
|
+
* `trackingVersion` counter, which increments whenever the consumer is about to re-run any reactive
|
|
10057
|
+
* reads it needs and establish a new set of dependencies as a result.
|
|
10058
|
+
*
|
|
10059
|
+
* Producers store the last `trackingVersion` they've seen from `Consumer`s which have read them.
|
|
10060
|
+
* This allows a producer to identify whether its record of the dependency is current or stale, by
|
|
10061
|
+
* comparing the consumer's `trackingVersion` to the version at which the dependency was
|
|
10062
|
+
* last observed.
|
|
10063
|
+
*/
|
|
10064
|
+
class ReactiveNode {
|
|
10065
|
+
constructor() {
|
|
10066
|
+
this.id = _nextReactiveId++;
|
|
10067
|
+
/**
|
|
10068
|
+
* A cached weak reference to this node, which will be used in `ReactiveEdge`s.
|
|
10069
|
+
*/
|
|
10070
|
+
this.ref = newWeakRef(this);
|
|
10071
|
+
/**
|
|
10072
|
+
* Edges to producers on which this node depends (in its consumer capacity).
|
|
10073
|
+
*/
|
|
10074
|
+
this.producers = new Map();
|
|
10075
|
+
/**
|
|
10076
|
+
* Edges to consumers on which this node depends (in its producer capacity).
|
|
10077
|
+
*/
|
|
10078
|
+
this.consumers = new Map();
|
|
10079
|
+
/**
|
|
10080
|
+
* Monotonically increasing counter representing a version of this `Consumer`'s
|
|
10081
|
+
* dependencies.
|
|
10082
|
+
*/
|
|
10083
|
+
this.trackingVersion = 0;
|
|
10084
|
+
/**
|
|
10085
|
+
* Monotonically increasing counter which increases when the value of this `Producer`
|
|
10086
|
+
* semantically changes.
|
|
10087
|
+
*/
|
|
10088
|
+
this.valueVersion = 0;
|
|
10089
|
+
}
|
|
10090
|
+
/**
|
|
10091
|
+
* Polls dependencies of a consumer to determine if they have actually changed.
|
|
10092
|
+
*
|
|
10093
|
+
* If this returns `false`, then even though the consumer may have previously been notified of a
|
|
10094
|
+
* change, the values of its dependencies have not actually changed and the consumer should not
|
|
10095
|
+
* rerun any reactions.
|
|
10096
|
+
*/
|
|
10097
|
+
consumerPollProducersForChange() {
|
|
10098
|
+
for (const [producerId, edge] of this.producers) {
|
|
10099
|
+
const producer = edge.producerNode.deref();
|
|
10100
|
+
if (producer === undefined || edge.atTrackingVersion !== this.trackingVersion) {
|
|
10101
|
+
// This dependency edge is stale, so remove it.
|
|
10102
|
+
this.producers.delete(producerId);
|
|
10103
|
+
producer?.consumers.delete(this.id);
|
|
10104
|
+
continue;
|
|
10105
|
+
}
|
|
10106
|
+
if (producer.producerPollStatus(edge.seenValueVersion)) {
|
|
10107
|
+
// One of the dependencies reports a real value change.
|
|
10108
|
+
return true;
|
|
10109
|
+
}
|
|
10110
|
+
}
|
|
10111
|
+
// No dependency reported a real value change, so the `Consumer` has also not been
|
|
10112
|
+
// impacted.
|
|
10113
|
+
return false;
|
|
10114
|
+
}
|
|
10115
|
+
/**
|
|
10116
|
+
* Notify all consumers of this producer that its value may have changed.
|
|
10117
|
+
*/
|
|
10118
|
+
producerMayHaveChanged() {
|
|
10119
|
+
for (const [consumerId, edge] of this.consumers) {
|
|
10120
|
+
const consumer = edge.consumerNode.deref();
|
|
10121
|
+
if (consumer === undefined || consumer.trackingVersion !== edge.atTrackingVersion) {
|
|
10122
|
+
this.consumers.delete(consumerId);
|
|
10123
|
+
consumer?.producers.delete(this.id);
|
|
10124
|
+
continue;
|
|
10125
|
+
}
|
|
10126
|
+
consumer.onConsumerDependencyMayHaveChanged();
|
|
10127
|
+
}
|
|
10128
|
+
}
|
|
10129
|
+
/**
|
|
10130
|
+
* Mark that this producer node has been accessed in the current reactive context.
|
|
10131
|
+
*/
|
|
10132
|
+
producerAccessed() {
|
|
10133
|
+
if (activeConsumer === null) {
|
|
10134
|
+
return;
|
|
10135
|
+
}
|
|
10136
|
+
// Either create or update the dependency `Edge` in both directions.
|
|
10137
|
+
let edge = activeConsumer.producers.get(this.id);
|
|
10138
|
+
if (edge === undefined) {
|
|
10139
|
+
edge = {
|
|
10140
|
+
consumerNode: activeConsumer.ref,
|
|
10141
|
+
producerNode: this.ref,
|
|
10142
|
+
seenValueVersion: this.valueVersion,
|
|
10143
|
+
atTrackingVersion: activeConsumer.trackingVersion,
|
|
10144
|
+
};
|
|
10145
|
+
activeConsumer.producers.set(this.id, edge);
|
|
10146
|
+
this.consumers.set(activeConsumer.id, edge);
|
|
10147
|
+
}
|
|
10148
|
+
else {
|
|
10149
|
+
edge.seenValueVersion = this.valueVersion;
|
|
10150
|
+
edge.atTrackingVersion = activeConsumer.trackingVersion;
|
|
10151
|
+
}
|
|
10152
|
+
}
|
|
10153
|
+
/**
|
|
10154
|
+
* Whether this consumer currently has any producers registered.
|
|
10155
|
+
*/
|
|
10156
|
+
get hasProducers() {
|
|
10157
|
+
return this.producers.size > 0;
|
|
10158
|
+
}
|
|
10159
|
+
/**
|
|
10160
|
+
* Checks if a `Producer` has a current value which is different than the value
|
|
10161
|
+
* last seen at a specific version by a `Consumer` which recorded a dependency on
|
|
10162
|
+
* this `Producer`.
|
|
10163
|
+
*/
|
|
10164
|
+
producerPollStatus(lastSeenValueVersion) {
|
|
10165
|
+
// `producer.valueVersion` may be stale, but a mismatch still means that the value
|
|
10166
|
+
// last seen by the `Consumer` is also stale.
|
|
10167
|
+
if (this.valueVersion !== lastSeenValueVersion) {
|
|
10168
|
+
return true;
|
|
10169
|
+
}
|
|
10170
|
+
// Trigger the `Producer` to update its `valueVersion` if necessary.
|
|
10171
|
+
this.onProducerUpdateValueVersion();
|
|
10172
|
+
// At this point, we can trust `producer.valueVersion`.
|
|
10173
|
+
return this.valueVersion !== lastSeenValueVersion;
|
|
10174
|
+
}
|
|
10175
|
+
}
|
|
10176
|
+
|
|
10177
|
+
/**
|
|
10178
|
+
* Marks current view and all ancestors dirty.
|
|
10179
|
+
*
|
|
10180
|
+
* Returns the root view because it is found as a byproduct of marking the view tree
|
|
10181
|
+
* dirty, and can be used by methods that consume markViewDirty() to easily schedule
|
|
10182
|
+
* change detection. Otherwise, such methods would need to traverse up the view tree
|
|
10183
|
+
* an additional time to get the root view and schedule a tick on it.
|
|
10184
|
+
*
|
|
10185
|
+
* @param lView The starting LView to mark dirty
|
|
10186
|
+
* @returns the root LView
|
|
10187
|
+
*/
|
|
10188
|
+
function markViewDirty(lView) {
|
|
10189
|
+
while (lView) {
|
|
10190
|
+
lView[FLAGS] |= 32 /* LViewFlags.Dirty */;
|
|
10191
|
+
const parent = getLViewParent(lView);
|
|
10192
|
+
// Stop traversing up as soon as you find a root view that wasn't attached to any container
|
|
10193
|
+
if (isRootView(lView) && !parent) {
|
|
10194
|
+
return lView;
|
|
10195
|
+
}
|
|
10196
|
+
// continue otherwise
|
|
10197
|
+
lView = parent;
|
|
10198
|
+
}
|
|
10199
|
+
return null;
|
|
10200
|
+
}
|
|
10201
|
+
|
|
10202
|
+
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;
|
|
10203
|
+
class ReactiveLViewConsumer extends ReactiveNode {
|
|
10204
|
+
constructor() {
|
|
10205
|
+
super(...arguments);
|
|
10206
|
+
this._lView = null;
|
|
10207
|
+
}
|
|
10208
|
+
set lView(lView) {
|
|
10209
|
+
NG_DEV_MODE && assertEqual(this._lView, null, 'Consumer already associated with a view.');
|
|
10210
|
+
this._lView = lView;
|
|
10211
|
+
}
|
|
10212
|
+
onConsumerDependencyMayHaveChanged() {
|
|
10213
|
+
NG_DEV_MODE &&
|
|
10214
|
+
assertDefined(this._lView, 'Updating a signal during template or host binding execution is not allowed.');
|
|
10215
|
+
markViewDirty(this._lView);
|
|
10216
|
+
}
|
|
10217
|
+
onProducerUpdateValueVersion() {
|
|
10218
|
+
// This type doesn't implement the producer side of a `ReactiveNode`.
|
|
10219
|
+
}
|
|
10220
|
+
get hasReadASignal() {
|
|
10221
|
+
return this.hasProducers;
|
|
10222
|
+
}
|
|
10223
|
+
runInContext(fn, rf, ctx) {
|
|
10224
|
+
const prevConsumer = setActiveConsumer(this);
|
|
10225
|
+
this.trackingVersion++;
|
|
10226
|
+
try {
|
|
10227
|
+
fn(rf, ctx);
|
|
10228
|
+
}
|
|
10229
|
+
finally {
|
|
10230
|
+
setActiveConsumer(prevConsumer);
|
|
10231
|
+
}
|
|
10232
|
+
}
|
|
10233
|
+
destroy() {
|
|
10234
|
+
// Incrementing the version means that every producer which tries to update this consumer will
|
|
10235
|
+
// consider its record stale, and not notify.
|
|
10236
|
+
this.trackingVersion++;
|
|
10237
|
+
}
|
|
10238
|
+
}
|
|
10239
|
+
let currentConsumer = null;
|
|
10240
|
+
function getOrCreateCurrentLViewConsumer() {
|
|
10241
|
+
currentConsumer ??= new ReactiveLViewConsumer();
|
|
10242
|
+
return currentConsumer;
|
|
10243
|
+
}
|
|
10244
|
+
/**
|
|
10245
|
+
* Create a new template consumer pointing at the specified LView.
|
|
10246
|
+
* Sometimes, a previously created consumer may be reused, in order to save on allocations. In that
|
|
10247
|
+
* case, the LView will be updated.
|
|
10248
|
+
*/
|
|
10249
|
+
function getReactiveLViewConsumer(lView, slot) {
|
|
10250
|
+
return lView[slot] ?? getOrCreateCurrentLViewConsumer();
|
|
10251
|
+
}
|
|
10252
|
+
/**
|
|
10253
|
+
* Assigns the `currentTemplateContext` to its LView's `REACTIVE_CONSUMER` slot if there are tracked
|
|
10254
|
+
* producers.
|
|
10255
|
+
*
|
|
10256
|
+
* The presence of producers means that a signal was read while the consumer was the active
|
|
10257
|
+
* consumer.
|
|
10258
|
+
*
|
|
10259
|
+
* If no producers are present, we do not assign the current template context. This also means we
|
|
10260
|
+
* can just reuse the template context for the next LView.
|
|
10261
|
+
*/
|
|
10262
|
+
function commitLViewConsumerIfHasProducers(lView, slot) {
|
|
10263
|
+
const consumer = getOrCreateCurrentLViewConsumer();
|
|
10264
|
+
if (!consumer.hasReadASignal) {
|
|
10265
|
+
return;
|
|
10266
|
+
}
|
|
10267
|
+
lView[slot] = currentConsumer;
|
|
10268
|
+
consumer.lView = lView;
|
|
10269
|
+
currentConsumer = new ReactiveLViewConsumer();
|
|
10270
|
+
}
|
|
10271
|
+
|
|
9894
10272
|
/** A special value which designates that a value has not changed. */
|
|
9895
10273
|
const NO_CHANGE = (typeof ngDevMode === 'undefined' || ngDevMode) ? { __brand__: 'NO_CHANGE' } : {};
|
|
9896
10274
|
|
|
@@ -9973,6 +10351,22 @@ function runInInjectionContext(injector, fn) {
|
|
|
9973
10351
|
setInjectImplementation(previousInjectImplementation);
|
|
9974
10352
|
}
|
|
9975
10353
|
}
|
|
10354
|
+
/**
|
|
10355
|
+
* Asserts that the current stack frame is within an injection context and has access to `inject`.
|
|
10356
|
+
*
|
|
10357
|
+
* @param debugFn a reference to the function making the assertion (used for the error message).
|
|
10358
|
+
*
|
|
10359
|
+
* @publicApi
|
|
10360
|
+
*/
|
|
10361
|
+
function assertInInjectionContext(debugFn) {
|
|
10362
|
+
// Taking a `Function` instead of a string name here prevents the unminified name of the function
|
|
10363
|
+
// from being retained in the bundle regardless of minification.
|
|
10364
|
+
if (!getInjectImplementation() && !getCurrentInjector()) {
|
|
10365
|
+
throw new RuntimeError(-203 /* RuntimeErrorCode.MISSING_INJECTION_CONTEXT */, ngDevMode &&
|
|
10366
|
+
(debugFn.name +
|
|
10367
|
+
'() can only be used within an injection context such as a constructor, a factory function, a field initializer, or a function used with `runInInjectionContext`'));
|
|
10368
|
+
}
|
|
10369
|
+
}
|
|
9976
10370
|
|
|
9977
10371
|
/**
|
|
9978
10372
|
* A mapping of the @angular/core API surface used in generated expressions to the actual symbols.
|
|
@@ -10125,6 +10519,8 @@ function createInjectorWithoutInjectorInstances(defType, parent = null, addition
|
|
|
10125
10519
|
* @publicApi
|
|
10126
10520
|
*/
|
|
10127
10521
|
class Injector {
|
|
10522
|
+
static { this.THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND; }
|
|
10523
|
+
static { this.NULL = ( /* @__PURE__ */new NullInjector()); }
|
|
10128
10524
|
static create(options, parent) {
|
|
10129
10525
|
if (Array.isArray(options)) {
|
|
10130
10526
|
return createInjector({ name: '' }, parent, options, '');
|
|
@@ -10134,20 +10530,18 @@ class Injector {
|
|
|
10134
10530
|
return createInjector({ name }, options.parent, options.providers, name);
|
|
10135
10531
|
}
|
|
10136
10532
|
}
|
|
10533
|
+
/** @nocollapse */
|
|
10534
|
+
static { this.ɵprov = ɵɵdefineInjectable({
|
|
10535
|
+
token: Injector,
|
|
10536
|
+
providedIn: 'any',
|
|
10537
|
+
factory: () => ɵɵinject(INJECTOR),
|
|
10538
|
+
}); }
|
|
10539
|
+
/**
|
|
10540
|
+
* @internal
|
|
10541
|
+
* @nocollapse
|
|
10542
|
+
*/
|
|
10543
|
+
static { this.__NG_ELEMENT_ID__ = -1 /* InjectorMarkers.Injector */; }
|
|
10137
10544
|
}
|
|
10138
|
-
Injector.THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND;
|
|
10139
|
-
Injector.NULL = ( /* @__PURE__ */new NullInjector());
|
|
10140
|
-
/** @nocollapse */
|
|
10141
|
-
Injector.ɵprov = ɵɵdefineInjectable({
|
|
10142
|
-
token: Injector,
|
|
10143
|
-
providedIn: 'any',
|
|
10144
|
-
factory: () => ɵɵinject(INJECTOR),
|
|
10145
|
-
});
|
|
10146
|
-
/**
|
|
10147
|
-
* @internal
|
|
10148
|
-
* @nocollapse
|
|
10149
|
-
*/
|
|
10150
|
-
Injector.__NG_ELEMENT_ID__ = -1 /* InjectorMarkers.Injector */;
|
|
10151
10545
|
|
|
10152
10546
|
function findFirstClosedCycle(keys) {
|
|
10153
10547
|
const res = [];
|
|
@@ -10748,6 +11142,7 @@ class ReflectiveInjector {
|
|
|
10748
11142
|
}
|
|
10749
11143
|
}
|
|
10750
11144
|
class ReflectiveInjector_ {
|
|
11145
|
+
static { this.INJECTOR_KEY = ( /* @__PURE__ */ReflectiveKey.get(Injector)); }
|
|
10751
11146
|
/**
|
|
10752
11147
|
* Private
|
|
10753
11148
|
*/
|
|
@@ -10903,7 +11298,6 @@ class ReflectiveInjector_ {
|
|
|
10903
11298
|
return this.displayName;
|
|
10904
11299
|
}
|
|
10905
11300
|
}
|
|
10906
|
-
ReflectiveInjector_.INJECTOR_KEY = ( /* @__PURE__ */ReflectiveKey.get(Injector));
|
|
10907
11301
|
function _mapProviders(injector, fn) {
|
|
10908
11302
|
const res = [];
|
|
10909
11303
|
for (let i = 0; i < injector._providers.length; ++i) {
|
|
@@ -10977,6 +11371,7 @@ function processHostBindingOpCodes(tView, lView) {
|
|
|
10977
11371
|
const hostBindingOpCodes = tView.hostBindingOpCodes;
|
|
10978
11372
|
if (hostBindingOpCodes === null)
|
|
10979
11373
|
return;
|
|
11374
|
+
const consumer = getReactiveLViewConsumer(lView, REACTIVE_HOST_BINDING_CONSUMER);
|
|
10980
11375
|
try {
|
|
10981
11376
|
for (let i = 0; i < hostBindingOpCodes.length; i++) {
|
|
10982
11377
|
const opCode = hostBindingOpCodes[i];
|
|
@@ -10991,11 +11386,13 @@ function processHostBindingOpCodes(tView, lView) {
|
|
|
10991
11386
|
const hostBindingFn = hostBindingOpCodes[++i];
|
|
10992
11387
|
setBindingRootForHostBindings(bindingRootIndx, directiveIdx);
|
|
10993
11388
|
const context = lView[directiveIdx];
|
|
10994
|
-
hostBindingFn
|
|
11389
|
+
consumer.runInContext(hostBindingFn, 2 /* RenderFlags.Update */, context);
|
|
10995
11390
|
}
|
|
10996
11391
|
}
|
|
10997
11392
|
}
|
|
10998
11393
|
finally {
|
|
11394
|
+
lView[REACTIVE_HOST_BINDING_CONSUMER] === null &&
|
|
11395
|
+
commitLViewConsumerIfHasProducers(lView, REACTIVE_HOST_BINDING_CONSUMER);
|
|
10999
11396
|
setSelectedIndex(-1);
|
|
11000
11397
|
}
|
|
11001
11398
|
}
|
|
@@ -11051,6 +11448,7 @@ function createLView(parentLView, tView, context, flags, host, tHostNode, render
|
|
|
11051
11448
|
lView[ID] = getUniqueLViewId();
|
|
11052
11449
|
lView[HYDRATION] = hydrationInfo;
|
|
11053
11450
|
lView[EMBEDDED_VIEW_INJECTOR] = embeddedViewInjector;
|
|
11451
|
+
lView[REACTIVE_TEMPLATE_CONSUMER] = null;
|
|
11054
11452
|
ngDevMode &&
|
|
11055
11453
|
assertEqual(tView.type == 2 /* TViewType.Embedded */ ? parentLView !== null : true, true, 'Embedded views must have parentLView');
|
|
11056
11454
|
lView[DECLARATION_COMPONENT_VIEW] =
|
|
@@ -11335,6 +11733,7 @@ function refreshView(tView, lView, templateFn, context) {
|
|
|
11335
11733
|
}
|
|
11336
11734
|
}
|
|
11337
11735
|
function executeTemplate(tView, lView, templateFn, rf, context) {
|
|
11736
|
+
const consumer = getReactiveLViewConsumer(lView, REACTIVE_TEMPLATE_CONSUMER);
|
|
11338
11737
|
const prevSelectedIndex = getSelectedIndex();
|
|
11339
11738
|
const isUpdatePhase = rf & 2 /* RenderFlags.Update */;
|
|
11340
11739
|
try {
|
|
@@ -11346,9 +11745,12 @@ function executeTemplate(tView, lView, templateFn, rf, context) {
|
|
|
11346
11745
|
}
|
|
11347
11746
|
const preHookType = isUpdatePhase ? 2 /* ProfilerEvent.TemplateUpdateStart */ : 0 /* ProfilerEvent.TemplateCreateStart */;
|
|
11348
11747
|
profiler(preHookType, context);
|
|
11349
|
-
templateFn
|
|
11748
|
+
consumer.runInContext(templateFn, rf, context);
|
|
11350
11749
|
}
|
|
11351
11750
|
finally {
|
|
11751
|
+
if (lView[REACTIVE_TEMPLATE_CONSUMER] === null) {
|
|
11752
|
+
commitLViewConsumerIfHasProducers(lView, REACTIVE_TEMPLATE_CONSUMER);
|
|
11753
|
+
}
|
|
11352
11754
|
setSelectedIndex(prevSelectedIndex);
|
|
11353
11755
|
const postHookType = isUpdatePhase ? 3 /* ProfilerEvent.TemplateUpdateEnd */ : 1 /* ProfilerEvent.TemplateCreateEnd */;
|
|
11354
11756
|
profiler(postHookType, context);
|
|
@@ -12452,30 +12854,6 @@ function addToViewTree(lView, lViewOrLContainer) {
|
|
|
12452
12854
|
///////////////////////////////
|
|
12453
12855
|
//// Change detection
|
|
12454
12856
|
///////////////////////////////
|
|
12455
|
-
/**
|
|
12456
|
-
* Marks current view and all ancestors dirty.
|
|
12457
|
-
*
|
|
12458
|
-
* Returns the root view because it is found as a byproduct of marking the view tree
|
|
12459
|
-
* dirty, and can be used by methods that consume markViewDirty() to easily schedule
|
|
12460
|
-
* change detection. Otherwise, such methods would need to traverse up the view tree
|
|
12461
|
-
* an additional time to get the root view and schedule a tick on it.
|
|
12462
|
-
*
|
|
12463
|
-
* @param lView The starting LView to mark dirty
|
|
12464
|
-
* @returns the root LView
|
|
12465
|
-
*/
|
|
12466
|
-
function markViewDirty(lView) {
|
|
12467
|
-
while (lView) {
|
|
12468
|
-
lView[FLAGS] |= 32 /* LViewFlags.Dirty */;
|
|
12469
|
-
const parent = getLViewParent(lView);
|
|
12470
|
-
// Stop traversing up as soon as you find a root view that wasn't attached to any container
|
|
12471
|
-
if (isRootView(lView) && !parent) {
|
|
12472
|
-
return lView;
|
|
12473
|
-
}
|
|
12474
|
-
// continue otherwise
|
|
12475
|
-
lView = parent;
|
|
12476
|
-
}
|
|
12477
|
-
return null;
|
|
12478
|
-
}
|
|
12479
12857
|
function detectChangesInternal(tView, lView, context, notifyErrorHandler = true) {
|
|
12480
12858
|
const rendererFactory = lView[RENDERER_FACTORY];
|
|
12481
12859
|
// Check no changes mode is a dev only mode used to verify that bindings have not changed
|
|
@@ -13156,6 +13534,7 @@ class ComponentRef extends ComponentRef$1 {
|
|
|
13156
13534
|
this.location = location;
|
|
13157
13535
|
this._rootLView = _rootLView;
|
|
13158
13536
|
this._tNode = _tNode;
|
|
13537
|
+
this.previousInputValues = null;
|
|
13159
13538
|
this.instance = instance;
|
|
13160
13539
|
this.hostView = this.changeDetectorRef = new RootViewRef(_rootLView);
|
|
13161
13540
|
this.componentType = componentType;
|
|
@@ -13164,8 +13543,16 @@ class ComponentRef extends ComponentRef$1 {
|
|
|
13164
13543
|
const inputData = this._tNode.inputs;
|
|
13165
13544
|
let dataValue;
|
|
13166
13545
|
if (inputData !== null && (dataValue = inputData[name])) {
|
|
13546
|
+
this.previousInputValues ??= new Map();
|
|
13547
|
+
// Do not set the input if it is the same as the last value
|
|
13548
|
+
// This behavior matches `bindingUpdated` when binding inputs in templates.
|
|
13549
|
+
if (this.previousInputValues.has(name) &&
|
|
13550
|
+
Object.is(this.previousInputValues.get(name), value)) {
|
|
13551
|
+
return;
|
|
13552
|
+
}
|
|
13167
13553
|
const lView = this._rootLView;
|
|
13168
13554
|
setInputsForProperty(lView[TVIEW], lView, dataValue, name, value);
|
|
13555
|
+
this.previousInputValues.set(name, value);
|
|
13169
13556
|
markDirtyIfOnPush(lView, this._tNode.index);
|
|
13170
13557
|
}
|
|
13171
13558
|
else {
|
|
@@ -14380,40 +14767,443 @@ function detectChanges(component) {
|
|
|
14380
14767
|
detectChangesInternal(view[TVIEW], view, component);
|
|
14381
14768
|
}
|
|
14382
14769
|
|
|
14770
|
+
const AT_THIS_LOCATION = '<-- AT THIS LOCATION';
|
|
14383
14771
|
/**
|
|
14384
|
-
*
|
|
14385
|
-
*
|
|
14772
|
+
* Retrieves a user friendly string for a given TNodeType for use in
|
|
14773
|
+
* friendly error messages
|
|
14774
|
+
*
|
|
14775
|
+
* @param tNodeType
|
|
14776
|
+
* @returns
|
|
14386
14777
|
*/
|
|
14387
|
-
function
|
|
14388
|
-
|
|
14389
|
-
|
|
14390
|
-
|
|
14391
|
-
|
|
14392
|
-
|
|
14393
|
-
|
|
14778
|
+
function getFriendlyStringFromTNodeType(tNodeType) {
|
|
14779
|
+
switch (tNodeType) {
|
|
14780
|
+
case 4 /* TNodeType.Container */:
|
|
14781
|
+
return 'view container';
|
|
14782
|
+
case 2 /* TNodeType.Element */:
|
|
14783
|
+
return 'element';
|
|
14784
|
+
case 8 /* TNodeType.ElementContainer */:
|
|
14785
|
+
return 'ng-container';
|
|
14786
|
+
case 32 /* TNodeType.Icu */:
|
|
14787
|
+
return 'icu';
|
|
14788
|
+
case 64 /* TNodeType.Placeholder */:
|
|
14789
|
+
return 'i18n';
|
|
14790
|
+
case 16 /* TNodeType.Projection */:
|
|
14791
|
+
return 'projection';
|
|
14792
|
+
case 1 /* TNodeType.Text */:
|
|
14793
|
+
return 'text';
|
|
14794
|
+
default:
|
|
14795
|
+
// This should not happen as we cover all possible TNode types above.
|
|
14796
|
+
return '<unknown>';
|
|
14797
|
+
}
|
|
14798
|
+
}
|
|
14799
|
+
/**
|
|
14800
|
+
* Validates that provided nodes match during the hydration process.
|
|
14801
|
+
*/
|
|
14802
|
+
function validateMatchingNode(node, nodeType, tagName, lView, tNode, isViewContainerAnchor = false) {
|
|
14803
|
+
if (!node ||
|
|
14804
|
+
(node.nodeType !== nodeType ||
|
|
14805
|
+
(node.nodeType === Node.ELEMENT_NODE &&
|
|
14806
|
+
node.tagName.toLowerCase() !== tagName?.toLowerCase()))) {
|
|
14807
|
+
const expectedNode = shortRNodeDescription(nodeType, tagName, null);
|
|
14808
|
+
let header = `During hydration Angular expected ${expectedNode} but `;
|
|
14809
|
+
const hostComponentDef = getDeclarationComponentDef(lView);
|
|
14810
|
+
const componentClassName = hostComponentDef?.type?.name;
|
|
14811
|
+
const expected = `Angular expected this DOM:\n\n${describeExpectedDom(lView, tNode, isViewContainerAnchor)}\n\n`;
|
|
14812
|
+
let actual = '';
|
|
14813
|
+
if (!node) {
|
|
14814
|
+
// No node found during hydration.
|
|
14815
|
+
header += `the node was not found.\n\n`;
|
|
14816
|
+
}
|
|
14817
|
+
else {
|
|
14818
|
+
const actualNode = shortRNodeDescription(node.nodeType, node.tagName ?? null, node.textContent ?? null);
|
|
14819
|
+
header += `found ${actualNode}.\n\n`;
|
|
14820
|
+
actual = `Actual DOM is:\n\n${describeDomFromNode(node)}\n\n`;
|
|
14821
|
+
}
|
|
14822
|
+
const footer = getHydrationErrorFooter(componentClassName);
|
|
14823
|
+
const message = header + expected + actual + getHydrationAttributeNote() + footer;
|
|
14824
|
+
throw new RuntimeError(500 /* RuntimeErrorCode.HYDRATION_NODE_MISMATCH */, message);
|
|
14394
14825
|
}
|
|
14395
14826
|
}
|
|
14396
14827
|
/**
|
|
14397
|
-
*
|
|
14828
|
+
* Validates that a given node has sibling nodes
|
|
14398
14829
|
*/
|
|
14399
14830
|
function validateSiblingNodeExists(node) {
|
|
14400
14831
|
validateNodeExists(node);
|
|
14401
14832
|
if (!node.nextSibling) {
|
|
14402
|
-
|
|
14403
|
-
|
|
14833
|
+
const header = 'During hydration Angular expected more sibling nodes to be present.\n\n';
|
|
14834
|
+
const actual = `Actual DOM is:\n\n${describeDomFromNode(node)}\n\n`;
|
|
14835
|
+
const footer = getHydrationErrorFooter();
|
|
14836
|
+
const message = header + actual + footer;
|
|
14837
|
+
throw new RuntimeError(501 /* RuntimeErrorCode.HYDRATION_MISSING_SIBLINGS */, message);
|
|
14404
14838
|
}
|
|
14405
14839
|
}
|
|
14840
|
+
/**
|
|
14841
|
+
* Validates that a node exists or throws
|
|
14842
|
+
*/
|
|
14406
14843
|
function validateNodeExists(node) {
|
|
14407
14844
|
if (!node) {
|
|
14408
|
-
|
|
14409
|
-
|
|
14845
|
+
throw new RuntimeError(502 /* RuntimeErrorCode.HYDRATION_MISSING_NODE */, `Hydration expected an element to be present at this location.`);
|
|
14846
|
+
}
|
|
14847
|
+
}
|
|
14848
|
+
/**
|
|
14849
|
+
* Builds the hydration error message when a node is not found
|
|
14850
|
+
*
|
|
14851
|
+
* @param lView the LView where the node exists
|
|
14852
|
+
* @param tNode the TNode
|
|
14853
|
+
*/
|
|
14854
|
+
function nodeNotFoundError(lView, tNode) {
|
|
14855
|
+
const header = 'During serialization, Angular was unable to find an element in the DOM:\n\n';
|
|
14856
|
+
const expected = `${describeExpectedDom(lView, tNode, false)}\n\n`;
|
|
14857
|
+
const footer = getHydrationErrorFooter();
|
|
14858
|
+
throw new RuntimeError(502 /* RuntimeErrorCode.HYDRATION_MISSING_NODE */, header + expected + footer);
|
|
14859
|
+
}
|
|
14860
|
+
/**
|
|
14861
|
+
* Builds a hydration error message when a node is not found at a path location
|
|
14862
|
+
*
|
|
14863
|
+
* @param host the Host Node
|
|
14864
|
+
* @param path the path to the node
|
|
14865
|
+
*/
|
|
14866
|
+
function nodeNotFoundAtPathError(host, path) {
|
|
14867
|
+
const header = `During hydration Angular was unable to locate a node ` +
|
|
14868
|
+
`using the "${path}" path, starting from the ${describeRNode(host)} node.\n\n`;
|
|
14869
|
+
const footer = getHydrationErrorFooter();
|
|
14870
|
+
throw new RuntimeError(502 /* RuntimeErrorCode.HYDRATION_MISSING_NODE */, header + footer);
|
|
14871
|
+
}
|
|
14872
|
+
/**
|
|
14873
|
+
* Builds the hydration error message in the case that dom nodes are created outside of
|
|
14874
|
+
* the Angular context and are being used as projected nodes
|
|
14875
|
+
*
|
|
14876
|
+
* @param lView the LView
|
|
14877
|
+
* @param tNode the TNode
|
|
14878
|
+
* @returns an error
|
|
14879
|
+
*/
|
|
14880
|
+
function unsupportedProjectionOfDomNodes(rNode) {
|
|
14881
|
+
const header = 'During serialization, Angular detected DOM nodes ' +
|
|
14882
|
+
'that were created outside of Angular context and provided as projectable nodes ' +
|
|
14883
|
+
'(likely via `ViewContainerRef.createComponent` or `createComponent` APIs). ' +
|
|
14884
|
+
'Hydration is not supported for such cases, consider refactoring the code to avoid ' +
|
|
14885
|
+
'this pattern or using `ngSkipHydration` on the host element of the component.\n\n';
|
|
14886
|
+
const actual = `${describeDomFromNode(rNode)}\n\n`;
|
|
14887
|
+
const message = header + actual + getHydrationAttributeNote();
|
|
14888
|
+
return new RuntimeError(503 /* RuntimeErrorCode.UNSUPPORTED_PROJECTION_DOM_NODES */, message);
|
|
14889
|
+
}
|
|
14890
|
+
/**
|
|
14891
|
+
* Builds the hydration error message in the case that ngSkipHydration was used on a
|
|
14892
|
+
* node that is not a component host element or host binding
|
|
14893
|
+
*
|
|
14894
|
+
* @param rNode the HTML Element
|
|
14895
|
+
* @returns an error
|
|
14896
|
+
*/
|
|
14897
|
+
function invalidSkipHydrationHost(rNode) {
|
|
14898
|
+
const header = 'The `ngSkipHydration` flag is applied on a node ' +
|
|
14899
|
+
'that doesn\'t act as a component host. Hydration can be ' +
|
|
14900
|
+
'skipped only on per-component basis.\n\n';
|
|
14901
|
+
const actual = `${describeDomFromNode(rNode)}\n\n`;
|
|
14902
|
+
const footer = 'Please move the `ngSkipHydration` attribute to the component host element.';
|
|
14903
|
+
const message = header + actual + footer;
|
|
14904
|
+
return new RuntimeError(504 /* RuntimeErrorCode.INVALID_SKIP_HYDRATION_HOST */, message);
|
|
14905
|
+
}
|
|
14906
|
+
/**
|
|
14907
|
+
* Builds the hydration error message in the case that a user is attempting to enable
|
|
14908
|
+
* hydration on internationalized nodes, which is not yet supported.
|
|
14909
|
+
*
|
|
14910
|
+
* @param rNode the HTML Element
|
|
14911
|
+
* @returns an error
|
|
14912
|
+
*/
|
|
14913
|
+
function notYetSupportedI18nBlockError(rNode) {
|
|
14914
|
+
const header = 'Hydration for nodes marked with `i18n` is not yet supported. ' +
|
|
14915
|
+
'You can opt-out a component that uses `i18n` in a template using ' +
|
|
14916
|
+
'the `ngSkipHydration` attribute or fall back to the previous ' +
|
|
14917
|
+
'hydration logic (which re-creates the application structure).\n\n';
|
|
14918
|
+
const actual = `${describeDomFromNode(rNode)}\n\n`;
|
|
14919
|
+
const message = header + actual;
|
|
14920
|
+
return new RuntimeError(518 /* RuntimeErrorCode.HYDRATION_I18N_NOT_YET_SUPPORTED */, message);
|
|
14921
|
+
}
|
|
14922
|
+
// Stringification methods
|
|
14923
|
+
/**
|
|
14924
|
+
* Stringifies a given TNode's attributes
|
|
14925
|
+
*
|
|
14926
|
+
* @param tNode a provided TNode
|
|
14927
|
+
* @returns string
|
|
14928
|
+
*/
|
|
14929
|
+
function stringifyTNodeAttrs(tNode) {
|
|
14930
|
+
const results = [];
|
|
14931
|
+
if (tNode.attrs) {
|
|
14932
|
+
for (let i = 0; i < tNode.attrs.length;) {
|
|
14933
|
+
const attrName = tNode.attrs[i++];
|
|
14934
|
+
// Once we reach the first flag, we know that the list of
|
|
14935
|
+
// attributes is over.
|
|
14936
|
+
if (typeof attrName == 'number') {
|
|
14937
|
+
break;
|
|
14938
|
+
}
|
|
14939
|
+
const attrValue = tNode.attrs[i++];
|
|
14940
|
+
results.push(`${attrName}="${shorten(attrValue)}"`);
|
|
14941
|
+
}
|
|
14942
|
+
}
|
|
14943
|
+
return results.join(' ');
|
|
14944
|
+
}
|
|
14945
|
+
/**
|
|
14946
|
+
* The list of internal attributes that should be filtered out while
|
|
14947
|
+
* producing an error message.
|
|
14948
|
+
*/
|
|
14949
|
+
const internalAttrs = new Set(['ngh', 'ng-version', 'ng-server-context']);
|
|
14950
|
+
/**
|
|
14951
|
+
* Stringifies an HTML Element's attributes
|
|
14952
|
+
*
|
|
14953
|
+
* @param rNode an HTML Element
|
|
14954
|
+
* @returns string
|
|
14955
|
+
*/
|
|
14956
|
+
function stringifyRNodeAttrs(rNode) {
|
|
14957
|
+
const results = [];
|
|
14958
|
+
for (let i = 0; i < rNode.attributes.length; i++) {
|
|
14959
|
+
const attr = rNode.attributes[i];
|
|
14960
|
+
if (internalAttrs.has(attr.name))
|
|
14961
|
+
continue;
|
|
14962
|
+
results.push(`${attr.name}="${shorten(attr.value)}"`);
|
|
14963
|
+
}
|
|
14964
|
+
return results.join(' ');
|
|
14965
|
+
}
|
|
14966
|
+
// Methods for Describing the DOM
|
|
14967
|
+
/**
|
|
14968
|
+
* Converts a tNode to a helpful readable string value for use in error messages
|
|
14969
|
+
*
|
|
14970
|
+
* @param tNode a given TNode
|
|
14971
|
+
* @param innerContent the content of the node
|
|
14972
|
+
* @returns string
|
|
14973
|
+
*/
|
|
14974
|
+
function describeTNode(tNode, innerContent = '…') {
|
|
14975
|
+
switch (tNode.type) {
|
|
14976
|
+
case 1 /* TNodeType.Text */:
|
|
14977
|
+
const content = tNode.value ? `(${tNode.value})` : '';
|
|
14978
|
+
return `#text${content}`;
|
|
14979
|
+
case 2 /* TNodeType.Element */:
|
|
14980
|
+
const attrs = stringifyTNodeAttrs(tNode);
|
|
14981
|
+
const tag = tNode.value.toLowerCase();
|
|
14982
|
+
return `<${tag}${attrs ? ' ' + attrs : ''}>${innerContent}</${tag}>`;
|
|
14983
|
+
case 8 /* TNodeType.ElementContainer */:
|
|
14984
|
+
return '<!-- ng-container -->';
|
|
14985
|
+
case 4 /* TNodeType.Container */:
|
|
14986
|
+
return '<!-- container -->';
|
|
14987
|
+
default:
|
|
14988
|
+
const typeAsString = getFriendlyStringFromTNodeType(tNode.type);
|
|
14989
|
+
return `#node(${typeAsString})`;
|
|
14990
|
+
}
|
|
14991
|
+
}
|
|
14992
|
+
/**
|
|
14993
|
+
* Converts an RNode to a helpful readable string value for use in error messages
|
|
14994
|
+
*
|
|
14995
|
+
* @param rNode a given RNode
|
|
14996
|
+
* @param innerContent the content of the node
|
|
14997
|
+
* @returns string
|
|
14998
|
+
*/
|
|
14999
|
+
function describeRNode(rNode, innerContent = '…') {
|
|
15000
|
+
const node = rNode;
|
|
15001
|
+
switch (node.nodeType) {
|
|
15002
|
+
case Node.ELEMENT_NODE:
|
|
15003
|
+
const tag = node.tagName.toLowerCase();
|
|
15004
|
+
const attrs = stringifyRNodeAttrs(node);
|
|
15005
|
+
return `<${tag}${attrs ? ' ' + attrs : ''}>${innerContent}</${tag}>`;
|
|
15006
|
+
case Node.TEXT_NODE:
|
|
15007
|
+
const content = node.textContent ? shorten(node.textContent) : '';
|
|
15008
|
+
return `#text${content ? `(${content})` : ''}`;
|
|
15009
|
+
case Node.COMMENT_NODE:
|
|
15010
|
+
return `<!-- ${shorten(node.textContent ?? '')} -->`;
|
|
15011
|
+
default:
|
|
15012
|
+
return `#node(${node.nodeType})`;
|
|
15013
|
+
}
|
|
15014
|
+
}
|
|
15015
|
+
/**
|
|
15016
|
+
* Builds the string containing the expected DOM present given the LView and TNode
|
|
15017
|
+
* values for a readable error message
|
|
15018
|
+
*
|
|
15019
|
+
* @param lView the lView containing the DOM
|
|
15020
|
+
* @param tNode the tNode
|
|
15021
|
+
* @param isViewContainerAnchor boolean
|
|
15022
|
+
* @returns string
|
|
15023
|
+
*/
|
|
15024
|
+
function describeExpectedDom(lView, tNode, isViewContainerAnchor) {
|
|
15025
|
+
const spacer = ' ';
|
|
15026
|
+
let content = '';
|
|
15027
|
+
if (tNode.prev) {
|
|
15028
|
+
content += spacer + '…\n';
|
|
15029
|
+
content += spacer + describeTNode(tNode.prev) + '\n';
|
|
15030
|
+
}
|
|
15031
|
+
else if (tNode.type && tNode.type & 12 /* TNodeType.AnyContainer */) {
|
|
15032
|
+
content += spacer + '…\n';
|
|
15033
|
+
}
|
|
15034
|
+
if (isViewContainerAnchor) {
|
|
15035
|
+
content += spacer + describeTNode(tNode) + '\n';
|
|
15036
|
+
content += spacer + `<!-- container --> ${AT_THIS_LOCATION}\n`;
|
|
15037
|
+
}
|
|
15038
|
+
else {
|
|
15039
|
+
content += spacer + describeTNode(tNode) + ` ${AT_THIS_LOCATION}\n`;
|
|
15040
|
+
}
|
|
15041
|
+
content += spacer + '…\n';
|
|
15042
|
+
const parentRNode = tNode.type ? getParentRElement(lView[TVIEW], tNode, lView) : null;
|
|
15043
|
+
if (parentRNode) {
|
|
15044
|
+
content = describeRNode(parentRNode, '\n' + content);
|
|
15045
|
+
}
|
|
15046
|
+
return content;
|
|
15047
|
+
}
|
|
15048
|
+
/**
|
|
15049
|
+
* Builds the string containing the DOM present around a given RNode for a
|
|
15050
|
+
* readable error message
|
|
15051
|
+
*
|
|
15052
|
+
* @param node the RNode
|
|
15053
|
+
* @returns string
|
|
15054
|
+
*/
|
|
15055
|
+
function describeDomFromNode(node) {
|
|
15056
|
+
const spacer = ' ';
|
|
15057
|
+
let content = '';
|
|
15058
|
+
const currentNode = node;
|
|
15059
|
+
if (currentNode.previousSibling) {
|
|
15060
|
+
content += spacer + '…\n';
|
|
15061
|
+
content += spacer + describeRNode(currentNode.previousSibling) + '\n';
|
|
15062
|
+
}
|
|
15063
|
+
content += spacer + describeRNode(currentNode) + ` ${AT_THIS_LOCATION}\n`;
|
|
15064
|
+
if (node.nextSibling) {
|
|
15065
|
+
content += spacer + '…\n';
|
|
15066
|
+
}
|
|
15067
|
+
if (node.parentNode) {
|
|
15068
|
+
content = describeRNode(currentNode.parentNode, '\n' + content);
|
|
15069
|
+
}
|
|
15070
|
+
return content;
|
|
15071
|
+
}
|
|
15072
|
+
/**
|
|
15073
|
+
* Shortens the description of a given RNode by its type for readability
|
|
15074
|
+
*
|
|
15075
|
+
* @param nodeType the type of node
|
|
15076
|
+
* @param tagName the node tag name
|
|
15077
|
+
* @param textContent the text content in the node
|
|
15078
|
+
* @returns string
|
|
15079
|
+
*/
|
|
15080
|
+
function shortRNodeDescription(nodeType, tagName, textContent) {
|
|
15081
|
+
switch (nodeType) {
|
|
15082
|
+
case Node.ELEMENT_NODE:
|
|
15083
|
+
return `<${tagName.toLowerCase()}>`;
|
|
15084
|
+
case Node.TEXT_NODE:
|
|
15085
|
+
const content = textContent ? ` (with the "${shorten(textContent)}" content)` : '';
|
|
15086
|
+
return `a text node${content}`;
|
|
15087
|
+
case Node.COMMENT_NODE:
|
|
15088
|
+
return 'a comment node';
|
|
15089
|
+
default:
|
|
15090
|
+
return `#node(nodeType=${nodeType})`;
|
|
15091
|
+
}
|
|
15092
|
+
}
|
|
15093
|
+
/**
|
|
15094
|
+
* Builds the footer hydration error message
|
|
15095
|
+
*
|
|
15096
|
+
* @param componentClassName the name of the component class
|
|
15097
|
+
* @returns string
|
|
15098
|
+
*/
|
|
15099
|
+
function getHydrationErrorFooter(componentClassName) {
|
|
15100
|
+
const componentInfo = componentClassName ? `the "${componentClassName}"` : 'corresponding';
|
|
15101
|
+
return `To fix this problem:\n` +
|
|
15102
|
+
` * check ${componentInfo} component for hydration-related issues\n` +
|
|
15103
|
+
` * or skip hydration by adding the \`ngSkipHydration\` attribute ` +
|
|
15104
|
+
`to its host node in a template`;
|
|
15105
|
+
}
|
|
15106
|
+
/**
|
|
15107
|
+
* An attribute related note for hydration errors
|
|
15108
|
+
*/
|
|
15109
|
+
function getHydrationAttributeNote() {
|
|
15110
|
+
return 'Note: attributes are only displayed to better represent the DOM' +
|
|
15111
|
+
' but have no effect on hydration mismatches.\n\n';
|
|
15112
|
+
}
|
|
15113
|
+
// Node string utility functions
|
|
15114
|
+
/**
|
|
15115
|
+
* Strips all newlines out of a given string
|
|
15116
|
+
*
|
|
15117
|
+
* @param input a string to be cleared of new line characters
|
|
15118
|
+
* @returns
|
|
15119
|
+
*/
|
|
15120
|
+
function stripNewlines(input) {
|
|
15121
|
+
return input.replace(/\s+/gm, '');
|
|
15122
|
+
}
|
|
15123
|
+
/**
|
|
15124
|
+
* Reduces a string down to a maximum length of characters with ellipsis for readability
|
|
15125
|
+
*
|
|
15126
|
+
* @param input a string input
|
|
15127
|
+
* @param maxLength a maximum length in characters
|
|
15128
|
+
* @returns string
|
|
15129
|
+
*/
|
|
15130
|
+
function shorten(input, maxLength = 50) {
|
|
15131
|
+
if (!input) {
|
|
15132
|
+
return '';
|
|
15133
|
+
}
|
|
15134
|
+
input = stripNewlines(input);
|
|
15135
|
+
return input.length > maxLength ? `${input.substring(0, maxLength - 1)}…` : input;
|
|
15136
|
+
}
|
|
15137
|
+
|
|
15138
|
+
/**
|
|
15139
|
+
* Regexp that extracts a reference node information from the compressed node location.
|
|
15140
|
+
* The reference node is represented as either:
|
|
15141
|
+
* - a number which points to an LView slot
|
|
15142
|
+
* - the `b` char which indicates that the lookup should start from the `document.body`
|
|
15143
|
+
* - the `h` char to start lookup from the component host node (`lView[HOST]`)
|
|
15144
|
+
*/
|
|
15145
|
+
const REF_EXTRACTOR_REGEXP = new RegExp(`^(\\d+)*(${REFERENCE_NODE_BODY}|${REFERENCE_NODE_HOST})*(.*)`);
|
|
15146
|
+
/**
|
|
15147
|
+
* Helper function that takes a reference node location and a set of navigation steps
|
|
15148
|
+
* (from the reference node) to a target node and outputs a string that represents
|
|
15149
|
+
* a location.
|
|
15150
|
+
*
|
|
15151
|
+
* For example, given: referenceNode = 'b' (body) and path = ['firstChild', 'firstChild',
|
|
15152
|
+
* 'nextSibling'], the function returns: `bf2n`.
|
|
15153
|
+
*/
|
|
15154
|
+
function compressNodeLocation(referenceNode, path) {
|
|
15155
|
+
const result = [referenceNode];
|
|
15156
|
+
for (const segment of path) {
|
|
15157
|
+
const lastIdx = result.length - 1;
|
|
15158
|
+
if (lastIdx > 0 && result[lastIdx - 1] === segment) {
|
|
15159
|
+
// An empty string in a count slot represents 1 occurrence of an instruction.
|
|
15160
|
+
const value = (result[lastIdx] || 1);
|
|
15161
|
+
result[lastIdx] = value + 1;
|
|
15162
|
+
}
|
|
15163
|
+
else {
|
|
15164
|
+
// Adding a new segment to the path.
|
|
15165
|
+
// Using an empty string in a counter field to avoid encoding `1`s
|
|
15166
|
+
// into the path, since they are implicit (e.g. `f1n1` vs `fn`), so
|
|
15167
|
+
// it's enough to have a single char in this case.
|
|
15168
|
+
result.push(segment, '');
|
|
15169
|
+
}
|
|
15170
|
+
}
|
|
15171
|
+
return result.join('');
|
|
15172
|
+
}
|
|
15173
|
+
/**
|
|
15174
|
+
* Helper function that reverts the `compressNodeLocation` and transforms a given
|
|
15175
|
+
* string into an array where at 0th position there is a reference node info and
|
|
15176
|
+
* after that it contains information (in pairs) about a navigation step and the
|
|
15177
|
+
* number of repetitions.
|
|
15178
|
+
*
|
|
15179
|
+
* For example, the path like 'bf2n' will be transformed to:
|
|
15180
|
+
* ['b', 'firstChild', 2, 'nextSibling', 1].
|
|
15181
|
+
*
|
|
15182
|
+
* This information is later consumed by the code that navigates the DOM to find
|
|
15183
|
+
* a given node by its location.
|
|
15184
|
+
*/
|
|
15185
|
+
function decompressNodeLocation(path) {
|
|
15186
|
+
const matches = path.match(REF_EXTRACTOR_REGEXP);
|
|
15187
|
+
const [_, refNodeId, refNodeName, rest] = matches;
|
|
15188
|
+
// If a reference node is represented by an index, transform it to a number.
|
|
15189
|
+
const ref = refNodeId ? parseInt(refNodeId, 10) : refNodeName;
|
|
15190
|
+
const steps = [];
|
|
15191
|
+
// Match all segments in a path.
|
|
15192
|
+
for (const [_, step, count] of rest.matchAll(/(f|n)(\d*)/g)) {
|
|
15193
|
+
const repeat = parseInt(count, 10) || 1;
|
|
15194
|
+
steps.push(step, repeat);
|
|
14410
15195
|
}
|
|
15196
|
+
return [ref, ...steps];
|
|
14411
15197
|
}
|
|
14412
15198
|
|
|
14413
15199
|
/** Whether current TNode is a first node in an <ng-container>. */
|
|
14414
15200
|
function isFirstElementInNgContainer(tNode) {
|
|
14415
15201
|
return !tNode.prev && tNode.parent?.type === 8 /* TNodeType.ElementContainer */;
|
|
14416
15202
|
}
|
|
15203
|
+
/** Returns an instruction index (subtracting HEADER_OFFSET). */
|
|
15204
|
+
function getNoOffsetIndex(tNode) {
|
|
15205
|
+
return tNode.index - HEADER_OFFSET;
|
|
15206
|
+
}
|
|
14417
15207
|
/**
|
|
14418
15208
|
* Locate a node in DOM tree that corresponds to a given TNode.
|
|
14419
15209
|
*
|
|
@@ -14425,7 +15215,13 @@ function isFirstElementInNgContainer(tNode) {
|
|
|
14425
15215
|
*/
|
|
14426
15216
|
function locateNextRNode(hydrationInfo, tView, lView, tNode) {
|
|
14427
15217
|
let native = null;
|
|
14428
|
-
|
|
15218
|
+
const noOffsetIndex = getNoOffsetIndex(tNode);
|
|
15219
|
+
const nodes = hydrationInfo.data[NODES];
|
|
15220
|
+
if (nodes?.[noOffsetIndex]) {
|
|
15221
|
+
// We know the exact location of the node.
|
|
15222
|
+
native = locateRNodeByPath(nodes[noOffsetIndex], lView);
|
|
15223
|
+
}
|
|
15224
|
+
else if (tView.firstChild === tNode) {
|
|
14429
15225
|
// We create a first node in this view, so we use a reference
|
|
14430
15226
|
// to the first child in this DOM segment.
|
|
14431
15227
|
native = hydrationInfo.firstChild;
|
|
@@ -14438,7 +15234,7 @@ function locateNextRNode(hydrationInfo, tView, lView, tNode) {
|
|
|
14438
15234
|
assertDefined(previousTNode, 'Unexpected state: current TNode does not have a connection ' +
|
|
14439
15235
|
'to the previous node or a parent node.');
|
|
14440
15236
|
if (isFirstElementInNgContainer(tNode)) {
|
|
14441
|
-
const noOffsetParentIndex = tNode.parent
|
|
15237
|
+
const noOffsetParentIndex = getNoOffsetIndex(tNode.parent);
|
|
14442
15238
|
native = getSegmentHead(hydrationInfo, noOffsetParentIndex);
|
|
14443
15239
|
}
|
|
14444
15240
|
else {
|
|
@@ -14452,7 +15248,7 @@ function locateNextRNode(hydrationInfo, tView, lView, tNode) {
|
|
|
14452
15248
|
// represented in the DOM as `<div></div>...<!--container-->`.
|
|
14453
15249
|
// In this case, there are nodes *after* this element and we need to skip
|
|
14454
15250
|
// all of them to reach an element that we are looking for.
|
|
14455
|
-
const noOffsetPrevSiblingIndex = previousTNode
|
|
15251
|
+
const noOffsetPrevSiblingIndex = getNoOffsetIndex(previousTNode);
|
|
14456
15252
|
const segmentHead = getSegmentHead(hydrationInfo, noOffsetPrevSiblingIndex);
|
|
14457
15253
|
if (previousTNode.type === 2 /* TNodeType.Element */ && segmentHead) {
|
|
14458
15254
|
const numRootNodesToSkip = calcSerializedContainerSize(hydrationInfo, noOffsetPrevSiblingIndex);
|
|
@@ -14480,6 +15276,181 @@ function siblingAfter(skip, from) {
|
|
|
14480
15276
|
}
|
|
14481
15277
|
return currentNode;
|
|
14482
15278
|
}
|
|
15279
|
+
/**
|
|
15280
|
+
* Helper function to produce a string representation of the navigation steps
|
|
15281
|
+
* (in terms of `nextSibling` and `firstChild` navigations). Used in error
|
|
15282
|
+
* messages in dev mode.
|
|
15283
|
+
*/
|
|
15284
|
+
function stringifyNavigationInstructions(instructions) {
|
|
15285
|
+
const container = [];
|
|
15286
|
+
for (let i = 0; i < instructions.length; i += 2) {
|
|
15287
|
+
const step = instructions[i];
|
|
15288
|
+
const repeat = instructions[i + 1];
|
|
15289
|
+
for (let r = 0; r < repeat; r++) {
|
|
15290
|
+
container.push(step === NodeNavigationStep.FirstChild ? 'firstChild' : 'nextSibling');
|
|
15291
|
+
}
|
|
15292
|
+
}
|
|
15293
|
+
return container.join('.');
|
|
15294
|
+
}
|
|
15295
|
+
/**
|
|
15296
|
+
* Helper function that navigates from a starting point node (the `from` node)
|
|
15297
|
+
* using provided set of navigation instructions (within `path` argument).
|
|
15298
|
+
*/
|
|
15299
|
+
function navigateToNode(from, instructions) {
|
|
15300
|
+
let node = from;
|
|
15301
|
+
for (let i = 0; i < instructions.length; i += 2) {
|
|
15302
|
+
const step = instructions[i];
|
|
15303
|
+
const repeat = instructions[i + 1];
|
|
15304
|
+
for (let r = 0; r < repeat; r++) {
|
|
15305
|
+
if (ngDevMode && !node) {
|
|
15306
|
+
throw nodeNotFoundAtPathError(from, stringifyNavigationInstructions(instructions));
|
|
15307
|
+
}
|
|
15308
|
+
switch (step) {
|
|
15309
|
+
case NodeNavigationStep.FirstChild:
|
|
15310
|
+
node = node.firstChild;
|
|
15311
|
+
break;
|
|
15312
|
+
case NodeNavigationStep.NextSibling:
|
|
15313
|
+
node = node.nextSibling;
|
|
15314
|
+
break;
|
|
15315
|
+
}
|
|
15316
|
+
}
|
|
15317
|
+
}
|
|
15318
|
+
if (ngDevMode && !node) {
|
|
15319
|
+
throw nodeNotFoundAtPathError(from, stringifyNavigationInstructions(instructions));
|
|
15320
|
+
}
|
|
15321
|
+
return node;
|
|
15322
|
+
}
|
|
15323
|
+
/**
|
|
15324
|
+
* Locates an RNode given a set of navigation instructions (which also contains
|
|
15325
|
+
* a starting point node info).
|
|
15326
|
+
*/
|
|
15327
|
+
function locateRNodeByPath(path, lView) {
|
|
15328
|
+
const [referenceNode, ...navigationInstructions] = decompressNodeLocation(path);
|
|
15329
|
+
let ref;
|
|
15330
|
+
if (referenceNode === REFERENCE_NODE_HOST) {
|
|
15331
|
+
ref = lView[0];
|
|
15332
|
+
}
|
|
15333
|
+
else if (referenceNode === REFERENCE_NODE_BODY) {
|
|
15334
|
+
ref = ɵɵresolveBody(lView[0]);
|
|
15335
|
+
}
|
|
15336
|
+
else {
|
|
15337
|
+
const parentElementId = Number(referenceNode);
|
|
15338
|
+
ref = unwrapRNode(lView[parentElementId + HEADER_OFFSET]);
|
|
15339
|
+
}
|
|
15340
|
+
return navigateToNode(ref, navigationInstructions);
|
|
15341
|
+
}
|
|
15342
|
+
/**
|
|
15343
|
+
* Generate a list of DOM navigation operations to get from node `start` to node `finish`.
|
|
15344
|
+
*
|
|
15345
|
+
* Note: assumes that node `start` occurs before node `finish` in an in-order traversal of the DOM
|
|
15346
|
+
* tree. That is, we should be able to get from `start` to `finish` purely by using `.firstChild`
|
|
15347
|
+
* and `.nextSibling` operations.
|
|
15348
|
+
*/
|
|
15349
|
+
function navigateBetween(start, finish) {
|
|
15350
|
+
if (start === finish) {
|
|
15351
|
+
return [];
|
|
15352
|
+
}
|
|
15353
|
+
else if (start.parentElement == null || finish.parentElement == null) {
|
|
15354
|
+
return null;
|
|
15355
|
+
}
|
|
15356
|
+
else if (start.parentElement === finish.parentElement) {
|
|
15357
|
+
return navigateBetweenSiblings(start, finish);
|
|
15358
|
+
}
|
|
15359
|
+
else {
|
|
15360
|
+
// `finish` is a child of its parent, so the parent will always have a child.
|
|
15361
|
+
const parent = finish.parentElement;
|
|
15362
|
+
const parentPath = navigateBetween(start, parent);
|
|
15363
|
+
const childPath = navigateBetween(parent.firstChild, finish);
|
|
15364
|
+
if (!parentPath || !childPath)
|
|
15365
|
+
return null;
|
|
15366
|
+
return [
|
|
15367
|
+
// First navigate to `finish`'s parent
|
|
15368
|
+
...parentPath,
|
|
15369
|
+
// Then to its first child.
|
|
15370
|
+
NodeNavigationStep.FirstChild,
|
|
15371
|
+
// And finally from that node to `finish` (maybe a no-op if we're already there).
|
|
15372
|
+
...childPath,
|
|
15373
|
+
];
|
|
15374
|
+
}
|
|
15375
|
+
}
|
|
15376
|
+
/**
|
|
15377
|
+
* Calculates a path between 2 sibling nodes (generates a number of `NextSibling` navigations).
|
|
15378
|
+
*/
|
|
15379
|
+
function navigateBetweenSiblings(start, finish) {
|
|
15380
|
+
const nav = [];
|
|
15381
|
+
let node = null;
|
|
15382
|
+
for (node = start; node != null && node !== finish; node = node.nextSibling) {
|
|
15383
|
+
nav.push(NodeNavigationStep.NextSibling);
|
|
15384
|
+
}
|
|
15385
|
+
return node === null ? [] : nav;
|
|
15386
|
+
}
|
|
15387
|
+
/**
|
|
15388
|
+
* Calculates a path between 2 nodes in terms of `nextSibling` and `firstChild`
|
|
15389
|
+
* navigations:
|
|
15390
|
+
* - the `from` node is a known node, used as an starting point for the lookup
|
|
15391
|
+
* (the `fromNodeName` argument is a string representation of the node).
|
|
15392
|
+
* - the `to` node is a node that the runtime logic would be looking up,
|
|
15393
|
+
* using the path generated by this function.
|
|
15394
|
+
*/
|
|
15395
|
+
function calcPathBetween(from, to, fromNodeName) {
|
|
15396
|
+
const path = navigateBetween(from, to);
|
|
15397
|
+
return path === null ? null : compressNodeLocation(fromNodeName, path);
|
|
15398
|
+
}
|
|
15399
|
+
/**
|
|
15400
|
+
* Invoked at serialization time (on the server) when a set of navigation
|
|
15401
|
+
* instructions needs to be generated for a TNode.
|
|
15402
|
+
*/
|
|
15403
|
+
function calcPathForNode(tNode, lView) {
|
|
15404
|
+
const parentTNode = tNode.parent;
|
|
15405
|
+
let parentIndex;
|
|
15406
|
+
let parentRNode;
|
|
15407
|
+
let referenceNodeName;
|
|
15408
|
+
if (parentTNode === null) {
|
|
15409
|
+
// No parent TNode - use host element as a reference node.
|
|
15410
|
+
parentIndex = referenceNodeName = REFERENCE_NODE_HOST;
|
|
15411
|
+
parentRNode = lView[HOST];
|
|
15412
|
+
}
|
|
15413
|
+
else {
|
|
15414
|
+
// Use parent TNode as a reference node.
|
|
15415
|
+
parentIndex = parentTNode.index;
|
|
15416
|
+
parentRNode = unwrapRNode(lView[parentIndex]);
|
|
15417
|
+
referenceNodeName = renderStringify(parentIndex - HEADER_OFFSET);
|
|
15418
|
+
}
|
|
15419
|
+
let rNode = unwrapRNode(lView[tNode.index]);
|
|
15420
|
+
if (tNode.type & 12 /* TNodeType.AnyContainer */) {
|
|
15421
|
+
// For <ng-container> nodes, instead of serializing a reference
|
|
15422
|
+
// to the anchor comment node, serialize a location of the first
|
|
15423
|
+
// DOM element. Paired with the container size (serialized as a part
|
|
15424
|
+
// of `ngh.containers`), it should give enough information for runtime
|
|
15425
|
+
// to hydrate nodes in this container.
|
|
15426
|
+
const firstRNode = getFirstNativeNode(lView, tNode);
|
|
15427
|
+
// If container is not empty, use a reference to the first element,
|
|
15428
|
+
// otherwise, rNode would point to an anchor comment node.
|
|
15429
|
+
if (firstRNode) {
|
|
15430
|
+
rNode = firstRNode;
|
|
15431
|
+
}
|
|
15432
|
+
}
|
|
15433
|
+
let path = calcPathBetween(parentRNode, rNode, referenceNodeName);
|
|
15434
|
+
if (path === null && parentRNode !== rNode) {
|
|
15435
|
+
// Searching for a path between elements within a host node failed.
|
|
15436
|
+
// Trying to find a path to an element starting from the `document.body` instead.
|
|
15437
|
+
//
|
|
15438
|
+
// Important note: this type of reference is relatively unstable, since Angular
|
|
15439
|
+
// may not be able to control parts of the page that the runtime logic navigates
|
|
15440
|
+
// through. This is mostly needed to cover "portals" use-case (like menus, dialog boxes,
|
|
15441
|
+
// etc), where nodes are content-projected (including direct DOM manipulations) outside
|
|
15442
|
+
// of the host node. The better solution is to provide APIs to work with "portals",
|
|
15443
|
+
// at which point this code path would not be needed.
|
|
15444
|
+
const body = parentRNode.ownerDocument.body;
|
|
15445
|
+
path = calcPathBetween(body, rNode, REFERENCE_NODE_BODY);
|
|
15446
|
+
if (path === null) {
|
|
15447
|
+
// If the path is still empty, it's likely that this node is detached and
|
|
15448
|
+
// won't be found during hydration.
|
|
15449
|
+
throw nodeNotFoundError(lView, tNode);
|
|
15450
|
+
}
|
|
15451
|
+
}
|
|
15452
|
+
return path;
|
|
15453
|
+
}
|
|
14483
15454
|
|
|
14484
15455
|
function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
|
|
14485
15456
|
ngDevMode && assertFirstCreatePass(tView);
|
|
@@ -14556,7 +15527,7 @@ function createContainerAnchorImpl(tView, lView, tNode, index) {
|
|
|
14556
15527
|
*/
|
|
14557
15528
|
function locateOrCreateContainerAnchorImpl(tView, lView, tNode, index) {
|
|
14558
15529
|
const hydrationInfo = lView[HYDRATION];
|
|
14559
|
-
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
|
|
15530
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1() || isDisconnectedNode(hydrationInfo, index);
|
|
14560
15531
|
lastNodeWasCreated(isNodeCreationMode);
|
|
14561
15532
|
// Regular creation mode.
|
|
14562
15533
|
if (isNodeCreationMode) {
|
|
@@ -14565,11 +15536,8 @@ function locateOrCreateContainerAnchorImpl(tView, lView, tNode, index) {
|
|
|
14565
15536
|
// Hydration mode, looking up existing elements in DOM.
|
|
14566
15537
|
const currentRNode = locateNextRNode(hydrationInfo, tView, lView, tNode);
|
|
14567
15538
|
ngDevMode && validateNodeExists(currentRNode);
|
|
15539
|
+
setSegmentHead(hydrationInfo, index, currentRNode);
|
|
14568
15540
|
const viewContainerSize = calcSerializedContainerSize(hydrationInfo, index);
|
|
14569
|
-
// If this container is non-empty, store the first node as a segment head,
|
|
14570
|
-
// otherwise, this node is an anchor and segment head doesn't exist (thus `null`).
|
|
14571
|
-
const segmentHead = viewContainerSize > 0 ? currentRNode : null;
|
|
14572
|
-
setSegmentHead(hydrationInfo, index, segmentHead);
|
|
14573
15541
|
const comment = siblingAfter(viewContainerSize, currentRNode);
|
|
14574
15542
|
if (ngDevMode) {
|
|
14575
15543
|
validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
|
|
@@ -14825,7 +15793,7 @@ let _locateOrCreateElementNode = (tView, lView, tNode, renderer, name, index) =>
|
|
|
14825
15793
|
*/
|
|
14826
15794
|
function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name, index) {
|
|
14827
15795
|
const hydrationInfo = lView[HYDRATION];
|
|
14828
|
-
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
|
|
15796
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1() || isDisconnectedNode(hydrationInfo, index);
|
|
14829
15797
|
lastNodeWasCreated(isNodeCreationMode);
|
|
14830
15798
|
// Regular creation mode.
|
|
14831
15799
|
if (isNodeCreationMode) {
|
|
@@ -14849,10 +15817,17 @@ function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name, inde
|
|
|
14849
15817
|
// Checks if the skip hydration attribute is present during hydration so we know to
|
|
14850
15818
|
// skip attempting to hydrate this block.
|
|
14851
15819
|
if (hydrationInfo && hasNgSkipHydrationAttr(tNode)) {
|
|
14852
|
-
|
|
14853
|
-
|
|
14854
|
-
|
|
14855
|
-
|
|
15820
|
+
if (isComponentHost(tNode)) {
|
|
15821
|
+
enterSkipHydrationBlock(tNode);
|
|
15822
|
+
// Since this isn't hydratable, we need to empty the node
|
|
15823
|
+
// so there's no duplicate content after render
|
|
15824
|
+
clearElementContents(native);
|
|
15825
|
+
}
|
|
15826
|
+
else if (ngDevMode) {
|
|
15827
|
+
// If this is not a component host, throw an error.
|
|
15828
|
+
// Hydration can be skipped on per-component basis only.
|
|
15829
|
+
throw invalidSkipHydrationHost(native);
|
|
15830
|
+
}
|
|
14856
15831
|
}
|
|
14857
15832
|
return native;
|
|
14858
15833
|
}
|
|
@@ -14986,10 +15961,7 @@ function locateOrCreateElementContainerNode(tView, lView, tNode, index) {
|
|
|
14986
15961
|
ngDevMode &&
|
|
14987
15962
|
assertNumber(ngContainerSize, 'Unexpected state: hydrating an <ng-container>, ' +
|
|
14988
15963
|
'but no hydration info is available.');
|
|
14989
|
-
|
|
14990
|
-
// otherwise, this node is an anchor and segment head doesn't exist (thus `null`).
|
|
14991
|
-
const segmentHead = ngContainerSize > 0 ? currentRNode : null;
|
|
14992
|
-
setSegmentHead(hydrationInfo, index, segmentHead);
|
|
15964
|
+
setSegmentHead(hydrationInfo, index, currentRNode);
|
|
14993
15965
|
comment = siblingAfter(ngContainerSize, currentRNode);
|
|
14994
15966
|
if (ngDevMode) {
|
|
14995
15967
|
validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
|
|
@@ -15371,7 +16343,10 @@ function ɵɵprojection(nodeIndex, selectorIndex = 0, attrs) {
|
|
|
15371
16343
|
tProjectionNode.projection = selectorIndex;
|
|
15372
16344
|
// `<ng-content>` has no content
|
|
15373
16345
|
setCurrentTNodeAsNotParent();
|
|
15374
|
-
|
|
16346
|
+
const hydrationInfo = lView[HYDRATION];
|
|
16347
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
|
|
16348
|
+
if (isNodeCreationMode &&
|
|
16349
|
+
(tProjectionNode.flags & 32 /* TNodeFlags.isDetached */) !== 32 /* TNodeFlags.isDetached */) {
|
|
15375
16350
|
// re-distribution of projectable nodes is stored on a component's view level
|
|
15376
16351
|
applyProjection(tView, lView, tProjectionNode);
|
|
15377
16352
|
}
|
|
@@ -17292,8 +18267,11 @@ function isStylingValuePresent(value) {
|
|
|
17292
18267
|
* @param suffix
|
|
17293
18268
|
*/
|
|
17294
18269
|
function normalizeSuffix(value, suffix) {
|
|
17295
|
-
if (value == null
|
|
18270
|
+
if (value == null || value === '') {
|
|
17296
18271
|
// do nothing
|
|
18272
|
+
// Do not add the suffix if the value is going to be empty.
|
|
18273
|
+
// As it produce invalid CSS, which the browsers will automatically omit but Domino will not.
|
|
18274
|
+
// Example: `"left": "px;"` instead of `"left": ""`.
|
|
17297
18275
|
}
|
|
17298
18276
|
else if (typeof suffix === 'string') {
|
|
17299
18277
|
value = value + suffix;
|
|
@@ -17334,7 +18312,7 @@ function ɵɵtext(index, value = '') {
|
|
|
17334
18312
|
const tNode = tView.firstCreatePass ?
|
|
17335
18313
|
getOrCreateTNode(tView, adjustedIndex, 1 /* TNodeType.Text */, value, null) :
|
|
17336
18314
|
tView.data[adjustedIndex];
|
|
17337
|
-
const textNative = _locateOrCreateTextNode(tView, lView, tNode, value);
|
|
18315
|
+
const textNative = _locateOrCreateTextNode(tView, lView, tNode, value, index);
|
|
17338
18316
|
lView[adjustedIndex] = textNative;
|
|
17339
18317
|
if (wasLastNodeCreated()) {
|
|
17340
18318
|
appendChild(tView, lView, textNative, tNode);
|
|
@@ -17342,7 +18320,7 @@ function ɵɵtext(index, value = '') {
|
|
|
17342
18320
|
// Text nodes are self closing.
|
|
17343
18321
|
setCurrentTNode(tNode, false);
|
|
17344
18322
|
}
|
|
17345
|
-
let _locateOrCreateTextNode = (tView, lView, tNode, value) => {
|
|
18323
|
+
let _locateOrCreateTextNode = (tView, lView, tNode, value, index) => {
|
|
17346
18324
|
lastNodeWasCreated(true);
|
|
17347
18325
|
return createTextNode(lView[RENDERER], value);
|
|
17348
18326
|
};
|
|
@@ -17350,9 +18328,9 @@ let _locateOrCreateTextNode = (tView, lView, tNode, value) => {
|
|
|
17350
18328
|
* Enables hydration code path (to lookup existing elements in DOM)
|
|
17351
18329
|
* in addition to the regular creation mode of text nodes.
|
|
17352
18330
|
*/
|
|
17353
|
-
function locateOrCreateTextNodeImpl(tView, lView, tNode, value) {
|
|
18331
|
+
function locateOrCreateTextNodeImpl(tView, lView, tNode, value, index) {
|
|
17354
18332
|
const hydrationInfo = lView[HYDRATION];
|
|
17355
|
-
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
|
|
18333
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1() || isDisconnectedNode(hydrationInfo, index);
|
|
17356
18334
|
lastNodeWasCreated(isNodeCreationMode);
|
|
17357
18335
|
// Regular creation mode.
|
|
17358
18336
|
if (isNodeCreationMode) {
|
|
@@ -21160,13 +22138,13 @@ class StandaloneService {
|
|
|
21160
22138
|
this.cachedInjectors.clear();
|
|
21161
22139
|
}
|
|
21162
22140
|
}
|
|
22141
|
+
/** @nocollapse */
|
|
22142
|
+
static { this.ɵprov = ɵɵdefineInjectable({
|
|
22143
|
+
token: StandaloneService,
|
|
22144
|
+
providedIn: 'environment',
|
|
22145
|
+
factory: () => new StandaloneService(ɵɵinject(EnvironmentInjector)),
|
|
22146
|
+
}); }
|
|
21163
22147
|
}
|
|
21164
|
-
/** @nocollapse */
|
|
21165
|
-
StandaloneService.ɵprov = ɵɵdefineInjectable({
|
|
21166
|
-
token: StandaloneService,
|
|
21167
|
-
providedIn: 'environment',
|
|
21168
|
-
factory: () => new StandaloneService(ɵɵinject(EnvironmentInjector)),
|
|
21169
|
-
});
|
|
21170
22148
|
/**
|
|
21171
22149
|
* A feature that acts as a setup code for the {@link StandaloneService}.
|
|
21172
22150
|
*
|
|
@@ -22208,6 +23186,7 @@ function symbolIterator() {
|
|
|
22208
23186
|
* @publicApi
|
|
22209
23187
|
*/
|
|
22210
23188
|
class QueryList {
|
|
23189
|
+
static { Symbol.iterator; }
|
|
22211
23190
|
/**
|
|
22212
23191
|
* Returns `Observable` of `QueryList` notifying the subscriber of changes.
|
|
22213
23192
|
*/
|
|
@@ -22335,7 +23314,6 @@ class QueryList {
|
|
|
22335
23314
|
this.changes.unsubscribe();
|
|
22336
23315
|
}
|
|
22337
23316
|
}
|
|
22338
|
-
Symbol.iterator;
|
|
22339
23317
|
|
|
22340
23318
|
/**
|
|
22341
23319
|
* Represents an embedded template that can be used to instantiate embedded views.
|
|
@@ -22356,12 +23334,12 @@ Symbol.iterator;
|
|
|
22356
23334
|
* @publicApi
|
|
22357
23335
|
*/
|
|
22358
23336
|
class TemplateRef {
|
|
23337
|
+
/**
|
|
23338
|
+
* @internal
|
|
23339
|
+
* @nocollapse
|
|
23340
|
+
*/
|
|
23341
|
+
static { this.__NG_ELEMENT_ID__ = injectTemplateRef; }
|
|
22359
23342
|
}
|
|
22360
|
-
/**
|
|
22361
|
-
* @internal
|
|
22362
|
-
* @nocollapse
|
|
22363
|
-
*/
|
|
22364
|
-
TemplateRef.__NG_ELEMENT_ID__ = injectTemplateRef;
|
|
22365
23343
|
const ViewEngineTemplateRef = TemplateRef;
|
|
22366
23344
|
// TODO(alxhub): combine interface and implementation. Currently this is challenging since something
|
|
22367
23345
|
// in g3 depends on them being separate.
|
|
@@ -22460,6 +23438,56 @@ function removeDehydratedView(dehydratedView, renderer) {
|
|
|
22460
23438
|
}
|
|
22461
23439
|
}
|
|
22462
23440
|
}
|
|
23441
|
+
/**
|
|
23442
|
+
* Walks over all views within this LContainer invokes dehydrated views
|
|
23443
|
+
* cleanup function for each one.
|
|
23444
|
+
*/
|
|
23445
|
+
function cleanupLContainer(lContainer) {
|
|
23446
|
+
removeDehydratedViews(lContainer);
|
|
23447
|
+
for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
|
|
23448
|
+
cleanupLView(lContainer[i]);
|
|
23449
|
+
}
|
|
23450
|
+
}
|
|
23451
|
+
/**
|
|
23452
|
+
* Walks over `LContainer`s and components registered within
|
|
23453
|
+
* this LView and invokes dehydrated views cleanup function for each one.
|
|
23454
|
+
*/
|
|
23455
|
+
function cleanupLView(lView) {
|
|
23456
|
+
const tView = lView[TVIEW];
|
|
23457
|
+
for (let i = HEADER_OFFSET; i < tView.bindingStartIndex; i++) {
|
|
23458
|
+
if (isLContainer(lView[i])) {
|
|
23459
|
+
const lContainer = lView[i];
|
|
23460
|
+
cleanupLContainer(lContainer);
|
|
23461
|
+
}
|
|
23462
|
+
else if (Array.isArray(lView[i])) {
|
|
23463
|
+
// This is a component, enter the `cleanupLView` recursively.
|
|
23464
|
+
cleanupLView(lView[i]);
|
|
23465
|
+
}
|
|
23466
|
+
}
|
|
23467
|
+
}
|
|
23468
|
+
/**
|
|
23469
|
+
* Walks over all views registered within the ApplicationRef and removes
|
|
23470
|
+
* all dehydrated views from all `LContainer`s along the way.
|
|
23471
|
+
*/
|
|
23472
|
+
function cleanupDehydratedViews(appRef, pendingTasks) {
|
|
23473
|
+
// Wait once an app becomes stable and cleanup all views that
|
|
23474
|
+
// were not claimed during the application bootstrap process.
|
|
23475
|
+
// The timing is similar to when we kick off serialization on the server.
|
|
23476
|
+
const isStablePromise = appRef.isStable.pipe(first((isStable) => isStable)).toPromise();
|
|
23477
|
+
const pendingTasksPromise = pendingTasks.whenAllTasksComplete;
|
|
23478
|
+
return Promise.allSettled([isStablePromise, pendingTasksPromise]).then(() => {
|
|
23479
|
+
const viewRefs = appRef._views;
|
|
23480
|
+
for (const viewRef of viewRefs) {
|
|
23481
|
+
const lView = getComponentLViewForHydration(viewRef);
|
|
23482
|
+
// An `lView` might be `null` if a `ViewRef` represents
|
|
23483
|
+
// an embedded view (not a component view).
|
|
23484
|
+
if (lView !== null && lView[HOST] !== null) {
|
|
23485
|
+
cleanupLView(lView);
|
|
23486
|
+
ngDevMode && ngDevMode.dehydratedViewsCleanupRuns++;
|
|
23487
|
+
}
|
|
23488
|
+
}
|
|
23489
|
+
});
|
|
23490
|
+
}
|
|
22463
23491
|
|
|
22464
23492
|
/**
|
|
22465
23493
|
* Given a current DOM node and a serialized information about the views
|
|
@@ -22469,20 +23497,24 @@ function removeDehydratedView(dehydratedView, renderer) {
|
|
|
22469
23497
|
function locateDehydratedViewsInContainer(currentRNode, serializedViews) {
|
|
22470
23498
|
const dehydratedViews = [];
|
|
22471
23499
|
for (const serializedView of serializedViews) {
|
|
22472
|
-
|
|
22473
|
-
|
|
22474
|
-
|
|
22475
|
-
|
|
22476
|
-
|
|
22477
|
-
|
|
22478
|
-
|
|
22479
|
-
|
|
22480
|
-
|
|
22481
|
-
|
|
22482
|
-
|
|
22483
|
-
|
|
23500
|
+
// Repeats a view multiple times as needed, based on the serialized information
|
|
23501
|
+
// (for example, for *ngFor-produced views).
|
|
23502
|
+
for (let i = 0; i < (serializedView[MULTIPLIER] ?? 1); i++) {
|
|
23503
|
+
const view = {
|
|
23504
|
+
data: serializedView,
|
|
23505
|
+
firstChild: null,
|
|
23506
|
+
};
|
|
23507
|
+
if (serializedView[NUM_ROOT_NODES] > 0) {
|
|
23508
|
+
// Keep reference to the first node in this view,
|
|
23509
|
+
// so it can be accessed while invoking template instructions.
|
|
23510
|
+
view.firstChild = currentRNode;
|
|
23511
|
+
// Move over to the next node after this view, which can
|
|
23512
|
+
// either be a first node of the next view or an anchor comment
|
|
23513
|
+
// node after the last view in a container.
|
|
23514
|
+
currentRNode = siblingAfter(serializedView[NUM_ROOT_NODES], currentRNode);
|
|
23515
|
+
}
|
|
23516
|
+
dehydratedViews.push(view);
|
|
22484
23517
|
}
|
|
22485
|
-
dehydratedViews.push(view);
|
|
22486
23518
|
}
|
|
22487
23519
|
return [currentRNode, dehydratedViews];
|
|
22488
23520
|
}
|
|
@@ -22546,12 +23578,12 @@ function findMatchingDehydratedView(lContainer, template) {
|
|
|
22546
23578
|
* @publicApi
|
|
22547
23579
|
*/
|
|
22548
23580
|
class ViewContainerRef {
|
|
23581
|
+
/**
|
|
23582
|
+
* @internal
|
|
23583
|
+
* @nocollapse
|
|
23584
|
+
*/
|
|
23585
|
+
static { this.__NG_ELEMENT_ID__ = injectViewContainerRef; }
|
|
22549
23586
|
}
|
|
22550
|
-
/**
|
|
22551
|
-
* @internal
|
|
22552
|
-
* @nocollapse
|
|
22553
|
-
*/
|
|
22554
|
-
ViewContainerRef.__NG_ELEMENT_ID__ = injectViewContainerRef;
|
|
22555
23587
|
/**
|
|
22556
23588
|
* Creates a ViewContainerRef and stores it on the injector. Or, if the ViewContainerRef
|
|
22557
23589
|
* already exists, retrieves the existing ViewContainerRef.
|
|
@@ -22863,21 +23895,22 @@ function locateOrCreateAnchorNode(lContainer, hostLView, hostTNode, slotValue) {
|
|
|
22863
23895
|
if (lContainer[NATIVE] && lContainer[DEHYDRATED_VIEWS])
|
|
22864
23896
|
return;
|
|
22865
23897
|
const hydrationInfo = hostLView[HYDRATION];
|
|
22866
|
-
const
|
|
23898
|
+
const noOffsetIndex = hostTNode.index - HEADER_OFFSET;
|
|
23899
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock(hostTNode) ||
|
|
23900
|
+
isDisconnectedNode(hydrationInfo, noOffsetIndex);
|
|
22867
23901
|
// Regular creation mode.
|
|
22868
23902
|
if (isNodeCreationMode) {
|
|
22869
23903
|
return createAnchorNode(lContainer, hostLView, hostTNode, slotValue);
|
|
22870
23904
|
}
|
|
22871
23905
|
// Hydration mode, looking up an anchor node and dehydrated views in DOM.
|
|
22872
|
-
const
|
|
22873
|
-
const
|
|
22874
|
-
const serializedViews = hydrationInfo.data[CONTAINERS]?.[index];
|
|
23906
|
+
const currentRNode = getSegmentHead(hydrationInfo, noOffsetIndex);
|
|
23907
|
+
const serializedViews = hydrationInfo.data[CONTAINERS]?.[noOffsetIndex];
|
|
22875
23908
|
ngDevMode &&
|
|
22876
23909
|
assertDefined(serializedViews, 'Unexpected state: no hydration info available for a given TNode, ' +
|
|
22877
23910
|
'which represents a view container.');
|
|
22878
23911
|
const [commentNode, dehydratedViews] = locateDehydratedViewsInContainer(currentRNode, serializedViews);
|
|
22879
23912
|
if (ngDevMode) {
|
|
22880
|
-
validateMatchingNode(commentNode, Node.COMMENT_NODE, null, hostLView, hostTNode);
|
|
23913
|
+
validateMatchingNode(commentNode, Node.COMMENT_NODE, null, hostLView, hostTNode, true);
|
|
22881
23914
|
// Do not throw in case this node is already claimed (thus `false` as a second
|
|
22882
23915
|
// argument). If this container is created based on an `<ng-template>`, the comment
|
|
22883
23916
|
// node would be already claimed from the `template` instruction. If an element acts
|
|
@@ -23716,7 +24749,6 @@ function verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRo
|
|
|
23716
24749
|
];
|
|
23717
24750
|
exports.forEach(verifyExportsAreDeclaredOrReExported);
|
|
23718
24751
|
declarations.forEach(decl => verifyDeclarationIsUnique(decl, allowDuplicateDeclarationsInRoot));
|
|
23719
|
-
declarations.forEach(verifyComponentEntryComponentsIsPartOfNgModule);
|
|
23720
24752
|
const ngModule = getAnnotation(moduleType, 'NgModule');
|
|
23721
24753
|
if (ngModule) {
|
|
23722
24754
|
ngModule.imports &&
|
|
@@ -23726,8 +24758,6 @@ function verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRo
|
|
|
23726
24758
|
});
|
|
23727
24759
|
ngModule.bootstrap && deepForEach(ngModule.bootstrap, verifyCorrectBootstrapType);
|
|
23728
24760
|
ngModule.bootstrap && deepForEach(ngModule.bootstrap, verifyComponentIsPartOfNgModule);
|
|
23729
|
-
ngModule.entryComponents &&
|
|
23730
|
-
deepForEach(ngModule.entryComponents, verifyComponentIsPartOfNgModule);
|
|
23731
24761
|
}
|
|
23732
24762
|
// Throw Error if any errors were detected.
|
|
23733
24763
|
if (errors.length) {
|
|
@@ -23805,16 +24835,6 @@ function verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRo
|
|
|
23805
24835
|
`function for bootstrap instead.`);
|
|
23806
24836
|
}
|
|
23807
24837
|
}
|
|
23808
|
-
function verifyComponentEntryComponentsIsPartOfNgModule(type) {
|
|
23809
|
-
type = resolveForwardRef(type);
|
|
23810
|
-
if (getComponentDef$1(type)) {
|
|
23811
|
-
// We know we are component
|
|
23812
|
-
const component = getAnnotation(type, 'Component');
|
|
23813
|
-
if (component && component.entryComponents) {
|
|
23814
|
-
deepForEach(component.entryComponents, verifyComponentIsPartOfNgModule);
|
|
23815
|
-
}
|
|
23816
|
-
}
|
|
23817
|
-
}
|
|
23818
24838
|
function verifySemanticsOfNgModuleImport(type, importingModule) {
|
|
23819
24839
|
type = resolveForwardRef(type);
|
|
23820
24840
|
const directiveDef = getComponentDef$1(type) || getDirectiveDef(type);
|
|
@@ -24715,10 +25735,11 @@ class TestBedCompiler {
|
|
|
24715
25735
|
}
|
|
24716
25736
|
}
|
|
24717
25737
|
queueTypesFromModulesArray(arr) {
|
|
24718
|
-
// Because we may encounter the same NgModule
|
|
24719
|
-
// NgModule
|
|
24720
|
-
// encountered. In some test setups, this caching
|
|
24721
|
-
|
|
25738
|
+
// Because we may encounter the same NgModule or a standalone Component while processing
|
|
25739
|
+
// the dependencies of an NgModule or a standalone Component, we cache them in this set so we
|
|
25740
|
+
// can skip ones that have already been seen encountered. In some test setups, this caching
|
|
25741
|
+
// resulted in 10X runtime improvement.
|
|
25742
|
+
const processedDefs = new Set();
|
|
24722
25743
|
const queueTypesFromModulesArrayRecur = (arr) => {
|
|
24723
25744
|
for (const value of arr) {
|
|
24724
25745
|
if (Array.isArray(value)) {
|
|
@@ -24726,10 +25747,10 @@ class TestBedCompiler {
|
|
|
24726
25747
|
}
|
|
24727
25748
|
else if (hasNgModuleDef(value)) {
|
|
24728
25749
|
const def = value.ɵmod;
|
|
24729
|
-
if (
|
|
25750
|
+
if (processedDefs.has(def)) {
|
|
24730
25751
|
continue;
|
|
24731
25752
|
}
|
|
24732
|
-
|
|
25753
|
+
processedDefs.add(def);
|
|
24733
25754
|
// Look through declarations, imports, and exports, and queue
|
|
24734
25755
|
// everything found there.
|
|
24735
25756
|
this.queueTypeArray(maybeUnwrapFn(def.declarations), value);
|
|
@@ -24742,6 +25763,10 @@ class TestBedCompiler {
|
|
|
24742
25763
|
else if (isStandaloneComponent(value)) {
|
|
24743
25764
|
this.queueType(value, null);
|
|
24744
25765
|
const def = getComponentDef(value);
|
|
25766
|
+
if (processedDefs.has(def)) {
|
|
25767
|
+
continue;
|
|
25768
|
+
}
|
|
25769
|
+
processedDefs.add(def);
|
|
24745
25770
|
const dependencies = maybeUnwrapFn(def.dependencies ?? []);
|
|
24746
25771
|
dependencies.forEach((dependency) => {
|
|
24747
25772
|
// Note: in AOT, the `dependencies` might also contain regular
|
|
@@ -25109,6 +26134,7 @@ class TestBedImpl {
|
|
|
25109
26134
|
*/
|
|
25110
26135
|
this.globalCompilationChecked = false;
|
|
25111
26136
|
}
|
|
26137
|
+
static { this._INSTANCE = null; }
|
|
25112
26138
|
static get INSTANCE() {
|
|
25113
26139
|
return TestBedImpl._INSTANCE = TestBedImpl._INSTANCE || new TestBedImpl();
|
|
25114
26140
|
}
|
|
@@ -25518,7 +26544,6 @@ class TestBedImpl {
|
|
|
25518
26544
|
}
|
|
25519
26545
|
}
|
|
25520
26546
|
}
|
|
25521
|
-
TestBedImpl._INSTANCE = null;
|
|
25522
26547
|
/**
|
|
25523
26548
|
* @description
|
|
25524
26549
|
* Configures and initializes environment for unit testing and provides methods for
|