├── .github ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── 1-bug-report.yaml │ ├── 2-feature-request.yaml │ └── config.yml └── workflows │ └── dart.yml ├── .gitignore ├── .idea ├── .name ├── modules.xml └── runConfigurations │ ├── melos_bootstrap.xml │ └── melos_clean.xml ├── AUTHORS ├── CHANGELOG.md ├── LICENSE ├── README.md ├── _tests ├── .gitignore ├── LICENSE ├── README.md ├── analysis_options.yaml ├── build.debug.yaml ├── build.yaml ├── dart_test.yaml ├── lib │ ├── compiler.dart │ ├── matchers.dart │ ├── query_tests.dart │ └── test_util.dart ├── melos__tests.iml ├── mono_pkg.yaml ├── pubspec.yaml └── test │ ├── bootstrap │ └── run_app_test.dart │ ├── common │ ├── directives │ │ ├── for_test.dart │ │ ├── if_test.dart │ │ ├── ng_class_test.dart │ │ ├── ng_style_test.dart │ │ ├── ng_switch_test.dart │ │ └── ng_template_outlet_test.dart │ └── pipes │ │ ├── async_pipe_test.dart │ │ ├── date_pipe_test.dart │ │ ├── lowercase_pipe_test.dart │ │ ├── number_pipe_test.dart │ │ ├── replace_pipe_test.dart │ │ ├── slice_pipe_test.dart │ │ └── uppercase_pipe_test.dart │ ├── compiler │ ├── analyzed_class_test.dart │ ├── ast_directive_normalizer_test.dart │ ├── ast_template_optimize_test.dart │ ├── ast_template_parser_test.dart │ ├── expression_parser │ │ ├── analyzer_test.dart │ │ ├── parser_test.dart │ │ └── unparser.dart │ ├── output │ │ ├── abstract_emitter_test.dart │ │ ├── dart_emitter_test.dart │ │ └── path_util_test.dart │ ├── provider_forest_test.dart │ ├── schema │ │ └── dom_element_schema_registry_test.dart │ ├── schema_registry_mock.dart │ ├── selector_test.dart │ ├── shadow_css_test.dart │ ├── style_url_resolver_test.dart │ └── template_humanizer_util.dart │ ├── compiler_integration │ ├── errors_in_part_of_file_test.dart │ ├── inject_optional_non_nullable_test.dart │ ├── injectable_annotation_test.dart │ ├── invalid_binding_test.dart │ ├── invalid_change_detection_link_test.dart │ ├── invalid_component_test.dart │ ├── invalid_global_singleton_service_test.dart │ ├── invalid_host_annotations_test.dart │ ├── invalid_late_fields_test.dart │ ├── invalid_uri_test.dart │ ├── null_class_attribute_test.dart │ ├── on_push_validation_test.dart │ ├── unresolvable_annotation_test.dart │ ├── unresolvable_export_test.dart │ ├── unrevivable_const_test.dart │ └── unsupported_style_url_test.dart │ ├── core │ ├── application_ref_test.dart │ ├── change_detection │ │ ├── binding_test.dart │ │ ├── change_detection_link_test.dart │ │ ├── container_test.dart │ │ ├── detect_host_changes_test.dart │ │ ├── differs │ │ │ └── default_iterable_differ_test.dart │ │ ├── expect_no_changes_dev_mode_test.dart │ │ ├── mark_child_for_check_test.dart │ │ ├── mark_for_check_test.dart │ │ └── on_push_embedded_view_test.dart │ ├── crash_detection_test.dart │ ├── di │ │ └── visibility_test.dart │ ├── directive_inheritance_test.dart │ ├── directive_lifecycle_integration_test.dart │ ├── event_handler_test.dart │ ├── exports_statics.dart │ ├── exports_test.dart │ ├── generics │ │ ├── bound.dart │ │ └── generics_test.dart │ ├── host_annotation_test.dart │ ├── i18n_escape_test.dart │ ├── i18n_test.dart │ ├── linker │ │ ├── component_class_selector_test.dart │ │ ├── component_loader_test.dart │ │ ├── component_providers_test.dart │ │ ├── component_selector_test.dart │ │ ├── implicit_static_test.dart │ │ ├── integration │ │ │ ├── banana_contract_test.dart │ │ │ ├── binding_integration_test.dart │ │ │ ├── dependency_injection_test.dart │ │ │ ├── directive_integration_test.dart │ │ │ ├── misc_test.dart │ │ │ ├── ng_container_test.dart │ │ │ ├── on_push_test.dart │ │ │ ├── outputs_test.dart │ │ │ ├── reference_binding_test.dart │ │ │ ├── template_test.dart │ │ │ └── view_creation_test.dart │ │ ├── integration_dart_test.dart │ │ ├── nested_container_test.dart │ │ ├── nested_template_test.dart │ │ ├── ng_content_ref_test.dart │ │ ├── query_integration_test.dart │ │ ├── regression_integration_test.dart │ │ ├── security_integration_test.dart │ │ ├── shadowed_inherited_members_test.dart │ │ └── style_encapsulation_test.dart │ ├── ng_zone_test.dart │ ├── pipe_test.dart │ ├── query_html_element_test.dart │ ├── styling │ │ ├── clear_component_styles_test.dart │ │ ├── order_test.dart │ │ └── shim_test.dart │ ├── testability │ │ └── testability_test.dart │ └── view │ │ ├── projection_integration_test.dart │ │ ├── projection_test.dart │ │ └── view_child_regression_test.dart │ ├── devtools │ ├── inspector_test.dart │ └── reference_counter_test.dart │ ├── di │ ├── directive_test.dart │ ├── generated │ │ └── injector_use_value_test.dart │ └── injector_test.dart │ ├── directives │ └── ng_for_content_projection_test.dart │ ├── integration │ ├── query_content_test.dart │ ├── query_view_test.dart │ └── unicode_template_test.dart │ ├── lifecycle_hooks │ ├── after_changes_test.dart │ └── do_check_test.dart │ ├── platform │ └── dom │ │ └── events │ │ └── key_events_test.dart │ ├── resolve_util.dart │ ├── security │ ├── dom_sanitization_service_test.dart │ ├── html_sanitizer_test.dart │ ├── safe_inner_html_test.dart │ ├── style_sanitizer_test.dart │ └── url_sanitizer_test.dart │ ├── source_gen │ └── template_compiler │ │ └── find_components_test.dart │ └── templates │ ├── additional_expression_lib.dart │ └── additional_expression_test.dart ├── analysis_options.yaml ├── examples ├── README.md └── hello_world │ ├── LICENSE │ ├── README.md │ ├── _mono_pkg.yaml │ ├── analysis_options.yaml │ ├── build.yaml │ ├── melos_examples.hello_world.iml │ ├── melos_examples_hello_world.iml │ ├── pubspec.yaml │ └── web │ ├── favicon.png │ ├── index.html │ └── main.dart ├── goldens ├── LICENSE ├── README.md ├── analysis_options.yaml ├── build.yaml ├── melos_goldens.iml ├── pubspec.yaml ├── test │ ├── change_detection │ │ ├── boolean_coerced_inputs.dart │ │ ├── boolean_coerced_inputs.js.golden │ │ ├── boolean_coerced_inputs.template.dart.golden │ │ ├── change_detection_link.dart │ │ ├── change_detection_link.js.golden │ │ ├── change_detection_link.template.dart.golden │ │ ├── default.dart │ │ ├── default.js.golden │ │ ├── default.template.dart.golden │ │ ├── directive_change_detector.dart │ │ ├── directive_change_detector.js.golden │ │ ├── directive_change_detector.template.dart.golden │ │ ├── on_push.dart │ │ ├── on_push.js.golden │ │ └── on_push.template.dart.golden │ ├── dependency_injection │ │ ├── eager_existing_providers.dart │ │ ├── eager_existing_providers.js.golden │ │ ├── eager_existing_providers.template.dart.golden │ │ ├── generated_injector_large.dart │ │ ├── generated_injector_large.js.golden │ │ ├── generated_injector_large.template.dart.golden │ │ ├── generated_injector_small.dart │ │ ├── generated_injector_small.js.golden │ │ ├── generated_injector_small.template.dart.golden │ │ ├── injector_get_internal.dart │ │ ├── injector_get_internal.js.golden │ │ ├── injector_get_internal.template.dart.golden │ │ ├── inlined_providers.dart │ │ ├── inlined_providers.js.golden │ │ ├── inlined_providers.template.dart.golden │ │ ├── opaque_token.dart │ │ ├── opaque_token.js.golden │ │ ├── opaque_token.template.dart.golden │ │ ├── visibility.dart │ │ ├── visibility.js.golden │ │ └── visibility.template.dart.golden │ ├── devtools │ │ ├── inputs.dart │ │ ├── inputs.js.golden │ │ └── inputs.template.dart.golden │ ├── dom_bindings │ │ ├── events.dart │ │ ├── events.js.golden │ │ ├── events.template.dart.golden │ │ ├── host_annotations.dart │ │ ├── host_annotations.js.golden │ │ ├── host_annotations.template.dart.golden │ │ ├── html_properties.dart │ │ ├── html_properties.js.golden │ │ ├── html_properties.template.dart.golden │ │ ├── interpolate.dart │ │ ├── interpolate.js.golden │ │ └── interpolate.template.dart.golden │ ├── language │ │ ├── null_safety.dart │ │ ├── null_safety.js.golden │ │ └── null_safety.template.dart.golden │ ├── lifecycle_hooks │ │ ├── after_changes.dart │ │ ├── after_changes.js.golden │ │ ├── after_changes.template.dart.golden │ │ ├── after_queries.dart │ │ ├── after_queries.js.golden │ │ ├── after_queries.template.dart.golden │ │ ├── do_check.dart │ │ ├── do_check.js.golden │ │ ├── do_check.template.dart.golden │ │ ├── on_init_and_destroy.dart │ │ ├── on_init_and_destroy.js.golden │ │ └── on_init_and_destroy.template.dart.golden │ ├── nnbd │ │ ├── hello_world.dart │ │ ├── hello_world.js.golden │ │ └── hello_world.template.dart.golden │ └── templates │ │ ├── directive_star_syntax.dart │ │ ├── directive_star_syntax.js.golden │ │ ├── directive_star_syntax.template.dart.golden │ │ ├── encapsulation.dart │ │ ├── encapsulation.js.golden │ │ ├── encapsulation.template.dart.golden │ │ ├── generic_directives.dart │ │ ├── generic_directives.js.golden │ │ ├── generic_directives.template.dart.golden │ │ ├── i18n.dart │ │ ├── i18n.js.golden │ │ ├── i18n.template.dart.golden │ │ ├── large_templates.dart │ │ ├── large_templates.js.golden │ │ ├── large_templates.template.dart.golden │ │ ├── nested_structural_directives.dart │ │ ├── nested_structural_directives.js.golden │ │ ├── nested_structural_directives.template.dart.golden │ │ ├── pipes.dart │ │ ├── pipes.js.golden │ │ ├── pipes.template.dart.golden │ │ ├── queries.dart │ │ ├── queries.js.golden │ │ ├── queries.template.dart.golden │ │ ├── type_inference.dart │ │ ├── type_inference.js.golden │ │ ├── type_inference.template.dart.golden │ │ ├── whitespace.dart │ │ ├── whitespace.js.golden │ │ └── whitespace.template.dart.golden └── tool │ └── update.dart ├── melos.yaml ├── melos_angular.iml ├── mono_repo.yaml ├── ngast ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── dart_test.yaml ├── example │ └── README.md ├── lib │ ├── angular_ast.dart │ ├── ngast.dart │ └── src │ │ ├── ast.dart │ │ ├── ast │ │ ├── attribute.dart │ │ ├── close_element.dart │ │ ├── comment.dart │ │ ├── container.dart │ │ ├── content.dart │ │ ├── element.dart │ │ ├── event.dart │ │ ├── interface.dart │ │ ├── interpolation.dart │ │ ├── let_binding.dart │ │ ├── property.dart │ │ ├── reference.dart │ │ ├── sugar │ │ │ ├── annotation.dart │ │ │ ├── banana.dart │ │ │ └── star.dart │ │ ├── template.dart │ │ └── text.dart │ │ ├── exception_handler │ │ ├── angular_parser_exception.dart │ │ ├── exception_handler.dart │ │ └── exceptions.dart │ │ ├── expression │ │ ├── micro.dart │ │ └── micro │ │ │ ├── ast.dart │ │ │ ├── lexer.dart │ │ │ ├── parser.dart │ │ │ ├── scanner.dart │ │ │ └── token.dart │ │ ├── lexer.dart │ │ ├── parser.dart │ │ ├── parser │ │ ├── reader.dart │ │ └── recursive.dart │ │ ├── recovery_protocol │ │ ├── angular_analyzer_protocol.dart │ │ └── recovery_protocol.dart │ │ ├── scanner.dart │ │ ├── simple_tokenizer.dart │ │ ├── token │ │ ├── chars.dart │ │ ├── lexeme.dart │ │ ├── token_types.dart │ │ └── tokens.dart │ │ ├── visitor.dart │ │ └── visitors │ │ ├── desugar.dart │ │ ├── humanizing.dart │ │ ├── identity.dart │ │ ├── recursive.dart │ │ └── whitespace.dart ├── melos_ngast.iml ├── mono_pkg.yaml ├── pubspec.yaml └── test │ ├── ast_cli_tester.dart │ ├── ast_cli_tester_source.html │ ├── cli_tester.dart │ ├── e2e │ ├── e2e_template_tests.dart │ └── templates │ │ ├── fixed_material_tab_strip.html │ │ ├── material_button.html │ │ ├── material_checkbox.html │ │ ├── material_chip.html │ │ ├── material_chips.html │ │ ├── material_dialog.html │ │ ├── material_expansion_panel.html │ │ ├── material_input.html │ │ ├── material_popup.html │ │ ├── material_progress.html │ │ ├── material_toggle.html │ │ ├── scoreboard.html │ │ └── scorecard.html │ ├── expression │ └── micro │ │ ├── lexer_test.dart │ │ └── parser_test.dart │ ├── lexer_test.dart │ ├── parser_test.dart │ ├── random_generator_test │ └── random_tester.dart │ ├── recover_errors_lexer_test.dart │ ├── recover_errors_parser_test.dart │ ├── simple_token_test.dart │ ├── simple_tokenizer_test.dart │ ├── token_test.dart │ ├── visitor_test.dart │ └── whitespace_test.dart ├── ngcompiler ├── .pubignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── dart_test.yaml ├── example │ └── README.md ├── lib │ ├── v1 │ │ ├── angular_compiler.dart │ │ ├── cli.dart │ │ ├── kythe_utils.dart │ │ └── src │ │ │ ├── angular_compiler │ │ │ ├── analyzer.dart │ │ │ ├── analyzer │ │ │ │ ├── common.dart │ │ │ │ ├── di │ │ │ │ │ ├── dependencies.dart │ │ │ │ │ ├── global_singleton_services.dart │ │ │ │ │ ├── injector.dart │ │ │ │ │ ├── modules.dart │ │ │ │ │ ├── providers.dart │ │ │ │ │ └── tokens.dart │ │ │ │ ├── link.dart │ │ │ │ ├── types.dart │ │ │ │ └── view │ │ │ │ │ ├── directive.dart │ │ │ │ │ └── typed_reader.dart │ │ │ ├── asset.dart │ │ │ ├── cli │ │ │ │ ├── builder.dart │ │ │ │ ├── flags.dart │ │ │ │ ├── logging.dart │ │ │ │ ├── messages.dart │ │ │ │ └── messages │ │ │ │ │ └── messages.dart │ │ │ ├── emitter │ │ │ │ ├── injector.dart │ │ │ │ └── split_dart_emitter.dart │ │ │ ├── outliner.dart │ │ │ └── outliner │ │ │ │ └── collect_type_parameters.dart │ │ │ ├── compiler │ │ │ ├── analyzed_class.dart │ │ │ ├── angular_compiler.dart │ │ │ ├── aria_attributes.dart │ │ │ ├── ast_directive_normalizer.dart │ │ │ ├── attribute_matcher.dart │ │ │ ├── chars.dart │ │ │ ├── compile_metadata.dart │ │ │ ├── compiler_utils.dart │ │ │ ├── expression_parser │ │ │ │ ├── analyzer_parser.dart │ │ │ │ ├── ast.dart │ │ │ │ └── parser.dart │ │ │ ├── html_events.dart │ │ │ ├── html_tags.dart │ │ │ ├── i18n.dart │ │ │ ├── i18n │ │ │ │ ├── builder.dart │ │ │ │ ├── message.dart │ │ │ │ ├── metadata.dart │ │ │ │ └── property_visitor.dart │ │ │ ├── identifiers.dart │ │ │ ├── ir │ │ │ │ └── model.dart │ │ │ ├── js_split_facade.dart │ │ │ ├── module │ │ │ │ └── ng_compiler_module.dart │ │ │ ├── optimize_ir │ │ │ │ ├── merge_events.dart │ │ │ │ └── optimize_lifecycles.dart │ │ │ ├── output │ │ │ │ ├── abstract_emitter.dart │ │ │ │ ├── convert.dart │ │ │ │ ├── dart_emitter.dart │ │ │ │ ├── output_ast.dart │ │ │ │ └── path_util.dart │ │ │ ├── parse_util.dart │ │ │ ├── provider_parser.dart │ │ │ ├── schema │ │ │ │ ├── dom_element_schema_registry.dart │ │ │ │ ├── element_schema_registry.dart │ │ │ │ └── skip_selectors_validator.dart │ │ │ ├── security.dart │ │ │ ├── selector.dart │ │ │ ├── semantic_analysis │ │ │ │ ├── binding_converter.dart │ │ │ │ ├── directive_converter.dart │ │ │ │ ├── element_converter.dart │ │ │ │ └── matched_directive_converter.dart │ │ │ ├── source_module.dart │ │ │ ├── style_url_resolver.dart │ │ │ ├── stylesheet_compiler │ │ │ │ ├── builder.dart │ │ │ │ ├── processor.dart │ │ │ │ ├── shadow_css.dart │ │ │ │ └── style_compiler.dart │ │ │ ├── template_ast.dart │ │ │ ├── template_compiler.dart │ │ │ ├── template_optimize.dart │ │ │ ├── template_parser.dart │ │ │ ├── template_parser │ │ │ │ ├── ast_template_parser.dart │ │ │ │ ├── missing_directives_validator.dart │ │ │ │ └── recursive_template_visitor.dart │ │ │ ├── view_compiler │ │ │ │ ├── bound_value_converter.dart │ │ │ │ ├── compile_element.dart │ │ │ │ ├── compile_method.dart │ │ │ │ ├── compile_pipe.dart │ │ │ │ ├── compile_query.dart │ │ │ │ ├── compile_view.dart │ │ │ │ ├── constants.dart │ │ │ │ ├── devtools.dart │ │ │ │ ├── directive_compiler.dart │ │ │ │ ├── event_binder.dart │ │ │ │ ├── expression_converter.dart │ │ │ │ ├── interpolation_utils.dart │ │ │ │ ├── ir │ │ │ │ │ ├── provider_resolver.dart │ │ │ │ │ ├── provider_source.dart │ │ │ │ │ └── view_storage.dart │ │ │ │ ├── lifecycle_binder.dart │ │ │ │ ├── parse_utils.dart │ │ │ │ ├── property_binder.dart │ │ │ │ ├── provider_forest.dart │ │ │ │ ├── update_statement_visitor.dart │ │ │ │ ├── view_binder.dart │ │ │ │ ├── view_builder.dart │ │ │ │ ├── view_compiler.dart │ │ │ │ ├── view_compiler_utils.dart │ │ │ │ ├── view_name_resolver.dart │ │ │ │ └── view_style_linker.dart │ │ │ └── view_type.dart │ │ │ └── source_gen │ │ │ ├── common │ │ │ ├── annotation_matcher.dart │ │ │ └── url_resolver.dart │ │ │ └── template_compiler │ │ │ ├── annotation_information.dart │ │ │ ├── check_injectables.dart │ │ │ ├── code_builder.dart │ │ │ ├── compile_metadata.dart │ │ │ ├── component_visitor_exceptions.dart │ │ │ ├── dart_object_utils.dart │ │ │ ├── find_components.dart │ │ │ ├── generator.dart │ │ │ ├── lifecycle_hooks.dart │ │ │ ├── pipe_visitor.dart │ │ │ ├── provider_inference.dart │ │ │ ├── template_compiler_outputs.dart │ │ │ └── template_processor.dart │ └── v2 │ │ ├── analyzer.dart │ │ ├── asset.dart │ │ ├── context.dart │ │ └── src │ │ └── context │ │ └── build_error.dart ├── melos_ngcompiler.iml ├── mono_pkg.yaml ├── pubspec.yaml └── test │ ├── v1 │ └── angular_compiler │ │ ├── analyzer │ │ ├── di │ │ │ ├── dependency_reader_test.dart │ │ │ ├── module_reader_test.dart │ │ │ ├── provider_reader_test.dart │ │ │ └── token_reader_test.dart │ │ ├── types_test.dart │ │ └── view │ │ │ ├── directive_test.dart │ │ │ └── typed_reader_test.dart │ │ ├── emitter │ │ └── injector_test.dart │ │ ├── integration │ │ └── generate_injector_test.dart │ │ └── src │ │ ├── compile.dart │ │ └── resolve.dart │ └── v2 │ ├── analyzer_test.dart │ ├── context_test.dart │ └── testing │ ├── runtime_source_resolution.dart │ └── runtime_source_resolution_test.dart ├── ngdart ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── build.yaml ├── example │ └── README.md ├── lib │ ├── angular.dart │ ├── di.dart │ ├── experimental.dart │ ├── security.dart │ └── src │ │ ├── bootstrap │ │ ├── modules.dart │ │ └── run.dart │ │ ├── build.dart │ │ ├── common │ │ ├── directives.dart │ │ ├── directives │ │ │ ├── ng_class.dart │ │ │ ├── ng_for.dart │ │ │ ├── ng_for_identity.dart │ │ │ ├── ng_if.dart │ │ │ ├── ng_style.dart │ │ │ ├── ng_switch.dart │ │ │ └── ng_template_outlet.dart │ │ ├── pipes.dart │ │ └── pipes │ │ │ ├── async_pipe.dart │ │ │ ├── common_pipes.dart │ │ │ ├── date_pipe.dart │ │ │ ├── invalid_pipe_argument_exception.dart │ │ │ ├── lowercase_pipe.dart │ │ │ ├── number_pipe.dart │ │ │ ├── replace_pipe.dart │ │ │ ├── slice_pipe.dart │ │ │ └── uppercase_pipe.dart │ │ ├── core │ │ ├── application_ref.dart │ │ ├── application_tokens.dart │ │ ├── change_detection.dart │ │ ├── change_detection │ │ │ ├── change_detection.dart │ │ │ ├── change_detector_ref.dart │ │ │ ├── differs │ │ │ │ ├── default_iterable_differ.dart │ │ │ │ └── default_keyvalue_differ.dart │ │ │ ├── directive_change_detector.dart │ │ │ └── host.dart │ │ ├── exception_handler.dart │ │ ├── linker.dart │ │ ├── linker │ │ │ ├── app_view_utils.dart │ │ │ ├── component_factory.dart │ │ │ ├── component_loader.dart │ │ │ ├── element_ref.dart │ │ │ ├── ng_content_ref.dart │ │ │ ├── style_encapsulation.dart │ │ │ ├── template_ref.dart │ │ │ ├── view_container.dart │ │ │ ├── view_container_ref.dart │ │ │ ├── view_fragment.dart │ │ │ ├── view_ref.dart │ │ │ └── views │ │ │ │ ├── component_view.dart │ │ │ │ ├── dynamic_view.dart │ │ │ │ ├── embedded_view.dart │ │ │ │ ├── host_view.dart │ │ │ │ ├── render_view.dart │ │ │ │ └── view.dart │ │ └── zone │ │ │ └── ng_zone.dart │ │ ├── devtools.dart │ │ ├── devtools │ │ ├── component_inspector.dart │ │ ├── error.dart │ │ ├── inspector.dart │ │ ├── model.dart │ │ ├── model.g.dart │ │ └── reference_counter.dart │ │ ├── di │ │ ├── errors.dart │ │ └── injector.dart │ │ ├── meta.dart │ │ ├── meta │ │ ├── change_detection_constants.dart │ │ ├── change_detection_link.dart │ │ ├── di_arguments.dart │ │ ├── di_generate_injector.dart │ │ ├── di_modules.dart │ │ ├── di_providers.dart │ │ ├── di_tokens.dart │ │ ├── directives.dart │ │ ├── lifecycle_hooks.dart │ │ ├── typed.dart │ │ ├── view.dart │ │ └── visibility.dart │ │ ├── runtime │ │ ├── check_binding.dart │ │ ├── dom_events.dart │ │ ├── dom_helpers.dart │ │ ├── interpolate.dart │ │ ├── proxies.dart │ │ ├── queries.dart │ │ └── text_binding.dart │ │ ├── security │ │ ├── dom_sanitization_service.dart │ │ ├── html_sanitizer.dart │ │ ├── safe_html_adapter.dart │ │ ├── safe_inner_html.dart │ │ ├── sanitization_service.dart │ │ ├── style_sanitizer.dart │ │ └── url_sanitizer.dart │ │ ├── testability.dart │ │ ├── testability │ │ ├── js_api.dart │ │ ├── js_impl.dart │ │ └── testability.dart │ │ ├── utilities.dart │ │ └── utilities │ │ ├── is_dev_mode.dart │ │ ├── is_primitive.dart │ │ └── unsafe_cast.dart ├── melos_ngdart.iml ├── mono_pkg.yaml └── pubspec.yaml ├── ngforms ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── dart_test.yaml ├── example │ └── README.md ├── lib │ ├── angular_forms.dart │ ├── ngforms.dart │ └── src │ │ ├── directives.dart │ │ ├── directives │ │ ├── abstract_control_directive.dart │ │ ├── abstract_form.dart │ │ ├── checkbox_value_accessor.dart │ │ ├── control_container.dart │ │ ├── control_value_accessor.dart │ │ ├── default_value_accessor.dart │ │ ├── form_interface.dart │ │ ├── memorized_form.dart │ │ ├── ng_control.dart │ │ ├── ng_control_group.dart │ │ ├── ng_control_name.dart │ │ ├── ng_control_status.dart │ │ ├── ng_form.dart │ │ ├── ng_form_control.dart │ │ ├── ng_form_model.dart │ │ ├── ng_model.dart │ │ ├── normalize_validator.dart │ │ ├── number_value_accessor.dart │ │ ├── radio_control_value_accessor.dart │ │ ├── select_control_value_accessor.dart │ │ ├── shared.dart │ │ └── validators.dart │ │ ├── form_builder.dart │ │ ├── model.dart │ │ └── validators.dart ├── melos_ngforms.iml ├── mono_pkg.yaml ├── pubspec.yaml └── test │ ├── accessor_test.dart │ ├── directives_test.dart │ ├── form_builder_test.dart │ ├── integration_test.dart │ ├── memorized_form_test.dart │ ├── model_test.dart │ ├── ng_control_group_test.dart │ ├── ng_control_name_test.dart │ ├── ng_control_repeated_test.dart │ ├── ng_form_control_test.dart │ ├── ng_form_model_test.dart │ ├── ng_form_test.dart │ ├── ng_model_test.dart │ ├── validator_directives_test.dart │ └── validators_test.dart ├── ngrouter ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── build.yaml ├── dart_test.yaml ├── example │ └── README.md ├── lib │ ├── angular_router.dart │ ├── ngrouter.dart │ ├── src │ │ ├── constants.dart │ │ ├── directives │ │ │ ├── router_link_active_directive.dart │ │ │ ├── router_link_directive.dart │ │ │ └── router_outlet_directive.dart │ │ ├── lifecycle.dart │ │ ├── location.dart │ │ ├── location │ │ │ ├── base_href.dart │ │ │ ├── browser_platform_location.dart │ │ │ ├── hash_location_strategy.dart │ │ │ ├── location.dart │ │ │ ├── location_strategy.dart │ │ │ ├── path_location_strategy.dart │ │ │ ├── platform_location.dart │ │ │ └── testing │ │ │ │ └── mock_location_strategy.dart │ │ ├── route_definition.dart │ │ ├── route_path.dart │ │ ├── router │ │ │ ├── navigation_params.dart │ │ │ ├── router.dart │ │ │ ├── router_impl.dart │ │ │ ├── router_outlet_token.dart │ │ │ └── router_state.dart │ │ ├── router_hook.dart │ │ └── url.dart │ └── testing.dart ├── melos_ngrouter.iml ├── mono_pkg.yaml ├── pubspec.yaml └── test │ ├── directives │ ├── router_link_active_directive_test.dart │ └── router_link_directive_test.dart │ ├── lifecycle_test.dart │ ├── mock_location_strategy_test.dart │ ├── navigate_by_url_test.dart │ ├── navigation_queue_test.dart │ ├── on_navigation_start_test.dart │ ├── on_route_resolved_test.dart │ ├── redirect_parameters_navigation_test.dart │ ├── regression │ ├── empty_active_link_test.dart │ ├── empty_hash_test.dart │ ├── empty_path_test.dart │ ├── hash_location_strategy_test.dart │ ├── redirect_test.dart │ └── routing_state_crash_test.dart │ ├── revert_popstate_test.dart │ ├── route_definition_test.dart │ ├── route_path_test.dart │ ├── route_prefetcher_test.dart │ ├── router_hook_test.dart │ ├── update_location_on_popstate_test.dart │ └── url_test.dart ├── ngtest ├── .pubignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── dart_test.yaml ├── example │ └── README.md ├── lib │ ├── angular_test.dart │ ├── compatibility.dart │ ├── ngtest.dart │ └── src │ │ ├── bootstrap.dart │ │ ├── errors.dart │ │ ├── errors │ │ ├── generic_type_missing.dart │ │ ├── test_already_running.dart │ │ └── will_never_stabilize.dart │ │ ├── frontend.dart │ │ └── frontend │ │ ├── bed.dart │ │ ├── fixture.dart │ │ ├── ng_zone │ │ ├── base_stabilizer.dart │ │ ├── fake_time_stabilizer.dart │ │ ├── real_time_stabilizer.dart │ │ └── timer_hook_zone.dart │ │ └── stabilizer.dart ├── melos_ngtest.iml ├── mono_pkg.yaml ├── pubspec.yaml └── test │ ├── bootstrap_test.dart │ └── frontend │ ├── bed_error_test.dart │ ├── bed_lifecycle_test.dart │ ├── bed_static_test.dart │ ├── compatibility_test.dart │ ├── ng_zone_test.dart │ ├── override_test.dart │ └── stabilizer_test.dart ├── pubspec.yaml └── tool ├── ci.sh ├── dart_test_repo.yaml ├── package_versions.yaml └── update_versions.dart /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for taking the time to file an issue! 2 | 3 | In order to route, prioritize, and act on this as soon as possible please include: 4 | 5 | * [ ] Dart SDK Version (`dart --version`) 6 | * [ ] AngularDart Version (i.e. `4.0.0`, `5.0.0-alpha+5`, `MASTER`) 7 | * [ ] Whether you are using Windows, macOS, or Linux (if applicable) 8 | * [ ] Whether you are using Chrome, Safari, Firefox, Edge (if applicable) 9 | * [ ] Any other packages or constraints we should know about 10 | 11 | Missing some or all of the above might make the issue take longer or be impossible to act on. 12 | 13 | ---- 14 | 15 | For questions consider using Stack Overflow instead: 16 | https://stackoverflow.com/questions/tagged/angular-dart 17 | 18 | Also consider our Gitter channel for light-weight/quick discussions: 19 | https://gitter.im/angulardart/community 20 | 21 | ----- 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature-request.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angulardart-community/angular/4a3659fffa6b08f4ad7144e584c60197fd6218ff/.github/ISSUE_TEMPLATE/2-feature-request.yaml -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | # - name: Security issue disclosure 4 | # url: https://angular.io/guide/security#report-issues 5 | # about: Report a security issue in Angular Framework, CDK, Material, or CLI 6 | - name: AngularDart CLI 7 | url: https://github.com/angulardart-community/ngdart/issues/new/choose 8 | about: Issues and feature requests for the AngularDart CLI 9 | - name: Angular Components 10 | url: https://github.com/angulardart-community/angular_components/issues/new/choose 11 | about: Issues and feature requests for Angular Material 12 | - name: Support Request 13 | url: https://gitter.im/angulardart/community 14 | about: Questions and requests for support 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts generated by "pub". 2 | .packages 3 | pubspec.lock 4 | 5 | # Ignore artifacts generated by "firebase" 6 | .firebase/ 7 | 8 | # Files generated by dart tools. 9 | **/.dart_tool/ 10 | **/doc/api/ 11 | **/build/ 12 | *.log 13 | 14 | # melos 15 | # pubspec_overrides.yaml 16 | 17 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | angular -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/runConfigurations/melos_bootstrap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/runConfigurations/melos_clean.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # Below is a list of people and organizations that have contributed to the 2 | # AngularDart project. Names should be added to the list like so: 3 | # 4 | # Name/Organization 5 | 6 | Google Inc. 7 | Benjamin Dopplinger 8 | Benjamin Strauß 9 | Günter Zöchbauer 10 | Kulshekhar Kabra 11 | Martin Schuster 12 | Naoto Higuchi 13 | Patrice Chalin 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2020 Dart Project Authors https://dart.dev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /_tests/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore files generated by test/source_gen/template_compiler/generate.dart 2 | test/source_gen/template_compiler/test_files/**/*.template_*.check 3 | -------------------------------------------------------------------------------- /_tests/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2020 Dart Project Authors https://dart.dev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /_tests/README.md: -------------------------------------------------------------------------------- 1 | This package is all the unit and component tests for `package:ngdart`. They 2 | are maintained here in order to avoid declaring circular dependencies between 3 | `ngdart` and `ngtest`, as well as adding private testing infrastructure. 4 | -------------------------------------------------------------------------------- /_tests/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: ../analysis_options.yaml 2 | 3 | analyzer: 4 | errors: 5 | implementation_imports: ignore 6 | 7 | # False positives related to missing .template.dart files 8 | # Comment this rules while developing. 9 | argument_type_not_assignable: ignore 10 | invalid_assignment: ignore 11 | non_bool_condition: ignore 12 | return_of_invalid_type: ignore 13 | -------------------------------------------------------------------------------- /_tests/build.debug.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | build_web_compilers|entrypoint: 5 | generate_for: 6 | include: 7 | # Includes both the bootstrapped entrypoints as well as the original 8 | # entrypoints to enable easier debugging. 9 | - test/**_test.dart 10 | exclude: 11 | - test/**.vm_test.dart 12 | - test/**.node_test.dart 13 | - test/compiler/** 14 | - test/compiler_integration/** 15 | - test/source_gen/** 16 | - test/regression/vm/** 17 | - test/core/di/provider_test.dart* 18 | -------------------------------------------------------------------------------- /_tests/build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | build_web_compilers|entrypoint: 5 | generate_for: 6 | include: 7 | - test/**.browser_test.dart 8 | exclude: 9 | - test/compiler/** 10 | - test/compiler_integration/** 11 | - test/source_gen/** 12 | - test/regression/vm/** 13 | - test/core/di/provider_test.dart* 14 | -------------------------------------------------------------------------------- /_tests/dart_test.yaml: -------------------------------------------------------------------------------- 1 | # Include common configuration. 2 | include: ../tool/dart_test_repo.yaml 3 | 4 | presets: 5 | browser: 6 | platforms: 7 | - chrome 8 | paths: 9 | - test/bootstrap 10 | - test/common 11 | - test/core 12 | - test/di 13 | - test/integration 14 | - test/platform 15 | # re-integrate from 'tests' 16 | - test/devtools 17 | - test/directives 18 | - test/lifecycle_hooks 19 | - test/templates 20 | - test/security 21 | add_presets: [ci] 22 | 23 | vm: 24 | platforms: 25 | - vm 26 | paths: 27 | - test/compiler 28 | - test/compiler_integration 29 | - test/source_gen 30 | add_presets: [ci] 31 | -------------------------------------------------------------------------------- /_tests/lib/test_util.dart: -------------------------------------------------------------------------------- 1 | import 'package:test/test.dart'; 2 | 3 | Matcher throwsWith(String s) => 4 | throwsA(predicate((e) => e.toString().contains(s))); 5 | 6 | final throwsATypeError = throwsA(TypeMatcher()); 7 | -------------------------------------------------------------------------------- /_tests/melos__tests.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /_tests/mono_pkg.yaml: -------------------------------------------------------------------------------- 1 | sdk: 2 | - pubspec 3 | - dev 4 | - stable 5 | 6 | stages: 7 | - build: 8 | - command: dart run build_runner build --fail-on-severe 9 | - unit_test: 10 | - command: dart test -P vm 11 | - command: dart run build_runner test --fail-on-severe -- -P browser 12 | -------------------------------------------------------------------------------- /_tests/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: _tests 2 | description: Tests for AngularDart. 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ">=3.6.0 <4.0.0" 7 | 8 | resolution: workspace 9 | 10 | dependencies: 11 | build: ^2.4.1 12 | build_resolvers: ^2.4.2 13 | build_test: ^2.2.2 14 | collection: ^1.19.1 15 | glob: ^2.1.2 16 | js: ^0.7.1 17 | logging: ^1.3.0 18 | ngcompiler: ^3.0.0-dev.3 19 | ngdart: ^8.0.0-dev.4 20 | ngtest: ^5.0.0-dev.2 21 | source_gen: ^1.5.0 22 | test: ^1.25.9 23 | 24 | dev_dependencies: 25 | analyzer: ^6.5.0 26 | build_runner: ^2.4.12 27 | build_web_compilers: ^4.0.11 28 | csslib: ^1.0.2 29 | lints: ^5.0.0 30 | meta: ^1.16.0 31 | mockito: ^5.4.4 32 | package_config: ^2.1.1 33 | source_span: ^1.10.1 34 | term_glyph: ^1.2.1 35 | -------------------------------------------------------------------------------- /_tests/test/common/pipes/lowercase_pipe_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngdart/src/common/pipes/lowercase_pipe.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('LowerCasePipe', () { 6 | late String upper; 7 | late String lower; 8 | late LowerCasePipe pipe; 9 | setUp(() { 10 | lower = 'something'; 11 | upper = 'SOMETHING'; 12 | pipe = LowerCasePipe(); 13 | }); 14 | group('transform', () { 15 | test('should return lowercase', () { 16 | var val = pipe.transform(upper); 17 | expect(val, lower); 18 | }); 19 | test('should lowercase when there is a new value', () { 20 | var val = pipe.transform(upper); 21 | expect(val, lower); 22 | var val2 = pipe.transform('WAT'); 23 | expect(val2, 'wat'); 24 | }); 25 | }); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /_tests/test/common/pipes/number_pipe_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngdart/src/common/pipes/number_pipe.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('Number pipes', () { 6 | group('DecimalPipe', () { 7 | var pipe = DecimalPipe(); 8 | 9 | group('transform', () { 10 | test('should return correct value for numbers', () { 11 | expect(pipe.transform(12345), '12,345'); 12 | expect(pipe.transform(123, '.2'), '123.00'); 13 | expect(pipe.transform(1, '3.'), '001'); 14 | expect(pipe.transform(1.1, '3.4-5'), '001.1000'); 15 | expect(pipe.transform(1.123456, '3.4-5'), '001.12346'); 16 | expect(pipe.transform(1.1234), '1.123'); 17 | }); 18 | }); 19 | }); 20 | group('PercentPipe', () { 21 | var pipe = PercentPipe(); 22 | 23 | group('transform', () { 24 | test('should return correct value for numbers', () { 25 | expect(pipe.transform(1.23), '123%'); 26 | expect(pipe.transform(1.2, '.2'), '120.00%'); 27 | }); 28 | }); 29 | }); 30 | group('CurrencyPipe', () { 31 | var pipe = CurrencyPipe(); 32 | group('transform', () { 33 | test('should return correct value for numbers', () { 34 | expect(pipe.transform(123), 'USD123'); 35 | expect(pipe.transform(12, 'EUR', false, '.2'), 'EUR12.00'); 36 | }); 37 | }); 38 | }); 39 | }); 40 | } 41 | -------------------------------------------------------------------------------- /_tests/test/common/pipes/uppercase_pipe_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngdart/src/common/pipes/uppercase_pipe.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group('UpperCasePipe', () { 6 | late String upper; 7 | late String lower; 8 | late UpperCasePipe pipe; 9 | setUp(() { 10 | lower = 'something'; 11 | upper = 'SOMETHING'; 12 | pipe = UpperCasePipe(); 13 | }); 14 | group('transform', () { 15 | test('should return uppercase', () { 16 | var val = pipe.transform(lower); 17 | expect(val, upper); 18 | }); 19 | test('should uppercase when there is a new value', () { 20 | var val = pipe.transform(lower); 21 | expect(val, upper); 22 | var val2 = pipe.transform('wat'); 23 | expect(val2, 'WAT'); 24 | }); 25 | }); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /_tests/test/compiler/output/abstract_emitter_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngcompiler/v1/src/compiler/output/abstract_emitter.dart' 2 | show escapeSingleQuoteString; 3 | import 'package:test/test.dart'; 4 | 5 | void main() { 6 | group('AbstractEmitter', () { 7 | group('escapeSingleQuoteString', () { 8 | test('should escape single quotes', () { 9 | expect(escapeSingleQuoteString("'", false), r"'\''"); 10 | }); 11 | test('should escape backslash', () { 12 | expect(escapeSingleQuoteString('\\', false), r"'\\'"); 13 | }); 14 | test('should escape newlines', () { 15 | expect(escapeSingleQuoteString('\n', false), r"'\n'"); 16 | }); 17 | test('should escape carriage returns', () { 18 | expect(escapeSingleQuoteString('\r', false), r"'\r'"); 19 | }); 20 | test('should escape \$', () { 21 | expect(escapeSingleQuoteString('\$', true), "'\\\$'"); 22 | }); 23 | test('should not escape \$', () { 24 | expect(escapeSingleQuoteString('\$', false), "'\$'"); 25 | }); 26 | }); 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /_tests/test/compiler/output/path_util_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:_tests/test_util.dart'; 2 | import 'package:ngcompiler/v1/src/compiler/output/path_util.dart' 3 | show getImportModulePath; 4 | import 'package:test/test.dart'; 5 | 6 | void main() { 7 | group('PathUtils getImportModulePath', () { 8 | test('should calculate relative paths', () { 9 | expect( 10 | getImportModulePath( 11 | 'asset:somePkg/lib/modPath', 'asset:somePkg/lib/impPath'), 12 | 'impPath'); 13 | }); 14 | test('should calculate absolute paths', () { 15 | expect( 16 | getImportModulePath( 17 | 'asset:somePkg/lib/modPath', 'asset:someOtherPkg/lib/impPath'), 18 | 'package:someOtherPkg/impPath'); 19 | }); 20 | test('should not allow absolute imports of non lib modules', () { 21 | expect( 22 | () => getImportModulePath( 23 | 'asset:somePkg/lib/modPath', 'asset:somePkg/test/impPath'), 24 | throwsWith("Can't import url asset:somePkg/test/impPath from " 25 | 'asset:somePkg/lib/modPath')); 26 | }); 27 | test('should not allow non asset urls as base url', () { 28 | expect( 29 | () => getImportModulePath( 30 | 'http:somePkg/lib/modPath', 'asset:somePkg/test/impPath'), 31 | throwsWith('Url http:somePkg/lib/modPath is not a valid asset: url')); 32 | }); 33 | test('should allow non asset urls as import urls and pass them through', 34 | () { 35 | expect(getImportModulePath('asset:somePkg/lib/modPath', 'dart:html'), 36 | 'dart:html'); 37 | }); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /_tests/test/compiler/schema_registry_mock.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngcompiler/v1/src/compiler/schema/element_schema_registry.dart'; 2 | import 'package:ngcompiler/v1/src/compiler/security.dart'; 3 | 4 | class MockSchemaRegistry implements ElementSchemaRegistry { 5 | final Map existingProperties; 6 | final Map attrPropMapping; 7 | const MockSchemaRegistry(this.existingProperties, this.attrPropMapping); 8 | 9 | @override 10 | bool hasProperty(String tagName, String property) => 11 | existingProperties[property] ?? true; 12 | 13 | // Allows any attribute name to avoid validation errors in tests. 14 | @override 15 | bool hasAttribute(String tagName, String attributeName) => true; 16 | 17 | // Allows any event name to avoid validation errors in tests. 18 | @override 19 | bool hasEvent(String tagName, String eventName) => true; 20 | 21 | @override 22 | String getMappedPropName(String attrName) => 23 | attrPropMapping[attrName] ?? attrName; 24 | 25 | @override 26 | TemplateSecurityContext securityContext(String tagName, String property) { 27 | return TemplateSecurityContext.none; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /_tests/test/compiler_integration/errors_in_part_of_file_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:_tests/compiler.dart'; 2 | import 'package:ngcompiler/v2/context.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | void main() { 6 | CompileContext.overrideForTesting(); 7 | 8 | test('should throw meaningful error message if it is in part of dart file', 9 | () async { 10 | await compilesExpecting( 11 | """ 12 | import '$ngImport'; 13 | 14 | part 'rest.dart'; 15 | 16 | @Component( 17 | selector: 'major', 18 | template: '', 19 | ) 20 | class MajorComp {} 21 | """, 22 | include: { 23 | 'pkg|lib/rest.dart': """ 24 | part of 'input.dart'; 25 | 26 | @Component( 27 | selector: 'rest', 28 | template: '', 29 | styleUrls: ['rest.scss'], 30 | ) 31 | class RestComp {} 32 | """, 33 | }, 34 | errors: [ 35 | allOf( 36 | contains('Unsupported extension in styleUrls:'), 37 | contains('Only ".css" is supported'), 38 | ), 39 | ], 40 | ); 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /_tests/test/compiler_integration/invalid_binding_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:_tests/compiler.dart'; 2 | import 'package:ngcompiler/v2/context.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | void main() { 6 | setUp(CompileContext.overrideForTesting); 7 | 8 | test('should require integer value for "tabindex"', () async { 9 | await compilesExpecting(''' 10 | import '$ngImport'; 11 | 12 | @Component( 13 | selector: 'test', 14 | template: '
', 15 | ) 16 | class TestComponent {} 17 | ''', errors: [ 18 | contains('The "tabindex" attribute expects an integer value'), 19 | ]); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /_tests/test/compiler_integration/invalid_global_singleton_service_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:_tests/compiler.dart'; 2 | import 'package:ngcompiler/v2/context.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | void main() { 6 | CompileContext.overrideForTesting(); 7 | 8 | group('should prevent providing an app-wide, singleton service', () { 9 | test('from a generated injector', () async { 10 | await compilesExpecting(""" 11 | import '$ngImport'; 12 | 13 | @GenerateInjector([ 14 | ClassProvider(NgZone), 15 | ]) 16 | final injectorFactory = null; // OK for compiler tests. 17 | """, errors: [ 18 | allOf( 19 | contains('singleton service provided by the framework that cannot be ' 20 | 'overridden or manually provided'), 21 | containsSourceLocation(6, 15), 22 | ), 23 | ]); 24 | }); 25 | 26 | test('from a component', () async { 27 | await compilesExpecting(""" 28 | import '$ngImport'; 29 | 30 | @Component( 31 | selector: 'foo', 32 | template: '', 33 | providers: [ClassProvider(NgZone)], 34 | ) 35 | class Foo {} 36 | """, errors: [ 37 | allOf( 38 | contains('singleton service provided by the framework that cannot be ' 39 | 'overridden or manually provided'), 40 | containsSourceLocation(3, 9), 41 | ), 42 | ]); 43 | }); 44 | }); 45 | } 46 | -------------------------------------------------------------------------------- /_tests/test/compiler_integration/invalid_uri_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:_tests/compiler.dart'; 2 | import 'package:ngcompiler/v2/context.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | void main() { 6 | CompileContext.overrideForTesting(); 7 | 8 | test('should ignore on unrecognized import URLs', () async { 9 | await compilesNormally(""" 10 | import 'dart:badpackage/bad.dart'; 11 | """); 12 | }); 13 | 14 | test('should ignore on unrecognized export URLs', () async { 15 | await compilesNormally(""" 16 | export 'dart:badpackage/bad.dart'; 17 | """); 18 | }); 19 | 20 | test('should ignore on unrecognized part URLs', () async { 21 | await compilesNormally(""" 22 | part 'dart:badpackage/bad.dart'; 23 | """); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /_tests/test/compiler_integration/null_class_attribute_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:_tests/compiler.dart'; 2 | import 'package:ngcompiler/v2/context.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | void main() { 6 | CompileContext.overrideForTesting(); 7 | 8 | test('should not crash on null class names', () async { 9 | await compilesNormally(""" 10 | import '$ngImport'; 11 | 12 | @Component( 13 | selector: 'null-class', 14 | template: '
', 15 | ) 16 | class NullClassComponent {} 17 | """); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /_tests/test/compiler_integration/unsupported_style_url_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:_tests/compiler.dart'; 2 | import 'package:ngcompiler/v2/context.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | void main() { 6 | CompileContext.overrideForTesting(); 7 | 8 | test('should fail on a non-".css" file extension', () async { 9 | await compilesExpecting(""" 10 | import '$ngImport'; 11 | 12 | @Component( 13 | selector: 'example', 14 | template: '', 15 | styleUrls: [ 16 | 'example.scss', 17 | ], 18 | ) 19 | class Example {} 20 | """, errors: [ 21 | contains('Unsupported extension in styleUrls: "example.scss"'), 22 | ]); 23 | }); 24 | 25 | test('should fail on an invalid URI', () async { 26 | await compilesExpecting(""" 27 | import '$ngImport'; 28 | 29 | @Component( 30 | selector: 'example', 31 | template: '', 32 | styleUrls: [ 33 | // Intentionally mis-spell package as packages. 34 | 'packages:foo/foo.css', 35 | ], 36 | ) 37 | class Example {} 38 | """, errors: [ 39 | contains('Invalid Style URL: "packages:foo/foo.css"'), 40 | ]); 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /_tests/test/core/exports_statics.dart: -------------------------------------------------------------------------------- 1 | const String myConst = 'hello'; 2 | 3 | const List myList = [1, 2, 3]; 4 | 5 | enum MyEnum { a, b, c } 6 | 7 | String myFunc(String x) => '$x!!!'; 8 | 9 | void staticClickHandler() { 10 | clickHandled = true; 11 | } 12 | 13 | bool clickHandled = false; 14 | 15 | class MyClass { 16 | static final String staticField = 'static field'; 17 | static bool clickHandled = false; 18 | static String staticFunc(String x) => '$x???'; 19 | } 20 | -------------------------------------------------------------------------------- /_tests/test/core/generics/bound.dart: -------------------------------------------------------------------------------- 1 | /// Serves as a generic type parameter bound. 2 | /// 3 | /// This is intentionally declared in a separate target to test the workaround 4 | /// for b/111800117. 5 | class Bound {} 6 | -------------------------------------------------------------------------------- /_tests/test/core/linker/nested_container_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngdart/angular.dart'; 2 | import 'package:ngtest/angular_test.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | import 'nested_container_test.template.dart' as ng; 6 | 7 | void main() { 8 | test('should append after last root node of view container', () async { 9 | var testBed = NgTestBed(ng.createTestComponentFactory()); 10 | var testFixture = await testBed.create(); 11 | expect(testFixture.text, '1'); 12 | // Appending to the inner view container should work. 13 | await testFixture.update((component) { 14 | component.matrix[0].add(2); // Now [[1, 2]] 15 | }); 16 | expect(testFixture.text, '12'); 17 | // Appending to the outer view container should work. 18 | await testFixture.update((component) { 19 | component.matrix.add([3, 4]); 20 | }); 21 | expect(testFixture.text, '1234'); 22 | }); 23 | } 24 | 25 | @Component( 26 | selector: 'test', 27 | template: r''' 28 |
    29 | 30 |
  • 31 | {{cell}} 32 |
  • 33 |
    34 |
35 | ''', 36 | directives: [NgFor], 37 | ) 38 | class TestComponent { 39 | var matrix = [ 40 | [1], 41 | ]; 42 | } 43 | -------------------------------------------------------------------------------- /_tests/test/core/linker/shadowed_inherited_members_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngdart/angular.dart'; 2 | import 'package:ngtest/angular_test.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | import 'shadowed_inherited_members_test.template.dart' as ng; 6 | 7 | void main() { 8 | tearDown(disposeAnyRunningTest); 9 | 10 | test('should handle shadowed inherited members', () async { 11 | final testBed = NgTestBed( 12 | ng.createTestShadowedInheritedMembersFactory()); 13 | final testFixture = await testBed.create(); 14 | expect(testFixture.text, 'Hello world!'); 15 | }); 16 | } 17 | 18 | /// Shadows `AppView.rootEl`. 19 | void rootEl() {} 20 | 21 | @Component( 22 | selector: 'test', 23 | template: ''' 24 |
Hello world!
25 | ''', 26 | ) 27 | class TestShadowedInheritedMembers {} 28 | -------------------------------------------------------------------------------- /_tests/test/core/view/view_child_regression_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:html'; 2 | 3 | import 'package:ngdart/angular.dart'; 4 | import 'package:ngtest/angular_test.dart'; 5 | import 'package:test/test.dart'; 6 | 7 | import 'view_child_regression_test.template.dart' as ng; 8 | 9 | void main() { 10 | test('$ViewChild#nativeElement should be accessible', () async { 11 | final fixture = 12 | await NgTestBed(ng.createViewChildTestFactory()) 13 | .create(); 14 | await fixture.update((component) { 15 | expect(component.portalElement, isNull); 16 | component.showChildHost = true; 17 | }); 18 | await fixture.update((component) { 19 | expect(component.portalElement, isNotNull); 20 | expect(component.containerElement, isNotNull); 21 | expect(component.markerViewContainer, isNotNull); 22 | }); 23 | }); 24 | } 25 | 26 | @Component( 27 | selector: 'view-child-test', 28 | template: r''' 29 |
30 | 33 |
34 |
35 | ''', 36 | directives: [ 37 | ChildHostDirective, 38 | NgIf, 39 | ], 40 | ) 41 | class ViewChildTest { 42 | @ViewChild('portal', read: Element) 43 | Element? portalElement; 44 | 45 | @ViewChild('container', read: Element) 46 | Element? containerElement; 47 | 48 | @ViewChild('marker', read: ViewContainerRef) 49 | ViewContainerRef? markerViewContainer; 50 | 51 | var showChildHost = false; 52 | } 53 | 54 | @Directive( 55 | selector: '[childHost]', 56 | ) 57 | class ChildHostDirective {} 58 | -------------------------------------------------------------------------------- /_tests/test/integration/unicode_template_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngdart/angular.dart'; 2 | import 'package:ngtest/angular_test.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | import 'unicode_template_test.template.dart' as ng; 6 | 7 | // Source: https://github.com/angulardart/angular/issues/233. 8 | void main() { 9 | test('should be able to compile templates with unicode', () async { 10 | final testBed = NgTestBed(ng.createAppFactory()); 11 | final fixture = await testBed.create(); 12 | expect(fixture.text, allOf(contains('🎂'), contains('ΓΔ'), contains('↔↕'))); 13 | }); 14 | } 15 | 16 | @Component( 17 | selector: 'app', 18 | template: ''' 19 |
🎂
20 |
ΓΔ
21 |
↔↕
22 | ''', 23 | ) 24 | class App {} 25 | -------------------------------------------------------------------------------- /_tests/test/templates/additional_expression_lib.dart: -------------------------------------------------------------------------------- 1 | /// A support library imported by `additional_expression_test.dart`. 2 | library additional_expression_lib; 3 | 4 | /// A class with static members to be referenced by a template. 5 | class ExternalStaticClass { 6 | static String? nullString; 7 | static String returnsA() => 'A'; 8 | static const valueB = 'staticB'; 9 | } 10 | 11 | /// A top-level function to be referenced by a template. 12 | String toUppercase(String input) => input.toUpperCase(); 13 | 14 | /// A top-level field to be referneced by a template. 15 | const valueB = 'topLevelB'; 16 | 17 | /// A top-level field that is null. 18 | const String? nullString = null; 19 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # Extend the default sub-set of linter/analyzer rules used in google3. 2 | include: package:lints/recommended.yaml 3 | 4 | analyzer: 5 | language: 6 | strict-casts: true 7 | strict-raw-types: true 8 | errors: 9 | # Permanent inclusions: These are optional hints that are not default on. 10 | unused_element: warning 11 | unused_field: warning 12 | unused_local_variable: warning 13 | 14 | # Permanent exclusions: Unlikely to removed. 15 | # ===================== 16 | # Ignore our own deprecated symbols (too noisy). 17 | deprecated_member_use_from_same_package: ignore 18 | # Allow having TODOs in the code (too noisy). 19 | todo: ignore 20 | # Allow importing .template.dart files without an [explicit] analyzer error. 21 | uri_has_not_been_generated: ignore 22 | 23 | # Security exclusions: We are security reviewed separate from these lints. 24 | # ===================== 25 | unsafe_html: ignore 26 | 27 | # Temporary exclusions: Can be removed in the future. 28 | # ===================== 29 | # Re-enable once we no longer have 200+ analyzer related deprecations. 30 | deprecated_member_use: ignore 31 | 32 | linter: 33 | rules: 34 | - always_declare_return_types 35 | - prefer_single_quotes 36 | - directives_ordering 37 | - unawaited_futures 38 | - unsafe_html 39 | - use_super_parameters 40 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | Various canonical example applications for AngularDart. 2 | -------------------------------------------------------------------------------- /examples/hello_world/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2020 Dart Project Authors https://dart.dev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/hello_world/README.md: -------------------------------------------------------------------------------- 1 | An example of a simple "Hello World", using the normal bootstrap process. 2 | 3 | ## Running locally 4 | 5 | To debug locally with DDC: 6 | 7 | ```bash 8 | $ pub get 9 | $ webdev serve 10 | ``` 11 | 12 | To debug locally with Dart2JS, minified: 13 | 14 | ```bash 15 | $ pub get 16 | $ webdev serve --release 17 | ``` 18 | 19 | ## Building a binary 20 | 21 | ```bash 22 | $ pub get 23 | $ webdev build 24 | ``` 25 | -------------------------------------------------------------------------------- /examples/hello_world/_mono_pkg.yaml: -------------------------------------------------------------------------------- 1 | sdk: 2 | - 2.19.6 3 | - pubspec 4 | 5 | stages: 6 | - analyze: 7 | - format 8 | - analyze 9 | - build: 10 | - command: dart run build_runner build --fail-on-severe 11 | -------------------------------------------------------------------------------- /examples/hello_world/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: ../../analysis_options.yaml 2 | 3 | analyzer: 4 | errors: 5 | # False positive related to missing .template.dart files 6 | argument_type_not_assignable: ignore 7 | -------------------------------------------------------------------------------- /examples/hello_world/build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | build_web_compilers|entrypoint: 5 | generate_for: 6 | - web/main.dart 7 | release_options: 8 | dart2js_args: 9 | - -O4 10 | -------------------------------------------------------------------------------- /examples/hello_world/melos_examples.hello_world.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/hello_world/melos_examples_hello_world.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/hello_world/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: examples_hello_world 2 | 3 | environment: 4 | sdk: ">=3.6.0 <4.0.0" 5 | 6 | resolution: workspace 7 | 8 | dependencies: 9 | # No strict dependencies, we always use dependency_overrides. 10 | ngdart: ^8.0.0-dev.4 11 | 12 | dev_dependencies: 13 | build_runner: ^2.4.12 14 | build_web_compilers: ^4.0.11 15 | lints: ^5.0.0 16 | -------------------------------------------------------------------------------- /examples/hello_world/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angulardart-community/angular/4a3659fffa6b08f4ad7144e584c60197fd6218ff/examples/hello_world/web/favicon.png -------------------------------------------------------------------------------- /examples/hello_world/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hello World 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/hello_world/web/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngdart/angular.dart'; 2 | 3 | import 'main.template.dart' as ng; 4 | 5 | void main() { 6 | runApp(ng.HelloWorldComponentNgFactory); 7 | } 8 | 9 | @Component( 10 | selector: 'hello-world', 11 | template: 'Hello World', 12 | ) 13 | class HelloWorldComponent {} 14 | -------------------------------------------------------------------------------- /goldens/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2020 Dart Project Authors https://dart.dev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /goldens/README.md: -------------------------------------------------------------------------------- 1 | A destination for golden file testing. 2 | 3 | Use `dart run build_runner build -r` to build the golden files 4 | and `dart run tool/update.dart` to update the golden files. 5 | 6 | Currently when adding a new `a.dart` file, you must add a sibling 7 | `a.template.dart.golden` and `a.js.golden` file. 8 | -------------------------------------------------------------------------------- /goldens/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: ../analysis_options.yaml 2 | 3 | analyzer: 4 | errors: 5 | argument_type_not_assignable: ignore 6 | invalid_assignment: ignore 7 | -------------------------------------------------------------------------------- /goldens/build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | build_web_compilers:entrypoint: 5 | generate_for: 6 | - test/**.dart 7 | options: 8 | dart2js_args: 9 | - -O1 10 | - --no-source-maps 11 | -------------------------------------------------------------------------------- /goldens/melos_goldens.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /goldens/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: goldens 2 | description: Goldens for AngularDart. 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ">=3.6.0 <4.0.0" 7 | 8 | resolution: workspace 9 | 10 | dependencies: 11 | js: ^0.7.1 12 | meta: ^1.16.0 13 | ngdart: ^8.0.0-dev.4 14 | 15 | dev_dependencies: 16 | build_runner: ^2.4.12 17 | build_web_compilers: ^4.0.11 18 | dart_style: ^2.3.7 19 | glob: ^2.1.2 20 | lints: ^5.0.0 21 | path: ^1.9.1 22 | -------------------------------------------------------------------------------- /goldens/test/change_detection/boolean_coerced_inputs.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | library golden; 3 | 4 | import 'package:js/js.dart'; 5 | import 'package:ngdart/angular.dart'; 6 | 7 | import 'boolean_coerced_inputs.template.dart' as ng; 8 | 9 | /// Avoids Dart2JS thinking something is constant/unchanging. 10 | @JS() 11 | external T deopt([Object? any]); 12 | 13 | void main() { 14 | runApp(ng.createGoldenComponentFactory()); 15 | } 16 | 17 | @Component( 18 | selector: 'golden', 19 | directives: [ 20 | FancyButtonComponent, 21 | ], 22 | template: r''' 23 | 24 | 25 | 26 | 27 | 28 | 29 | ''', 30 | ) 31 | class GoldenComponent { 32 | bool value = deopt(); 33 | } 34 | 35 | @Component( 36 | selector: 'fancy-button', 37 | template: '', 38 | ) 39 | class FancyButtonComponent { 40 | @Input() 41 | set raised(bool raised) => deopt(raised); 42 | } 43 | -------------------------------------------------------------------------------- /goldens/test/change_detection/default.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | library golden; 3 | 4 | import 'package:js/js.dart'; 5 | import 'package:ngdart/angular.dart'; 6 | 7 | import 'default.template.dart' as ng; 8 | 9 | /// Avoids Dart2JS thinking something is constant/unchanging. 10 | @JS() 11 | external T deopt([Object? any]); 12 | 13 | void main() { 14 | runApp(ng.createGoldenComponentFactory()); 15 | } 16 | 17 | @Component( 18 | selector: 'golden', 19 | directives: [ 20 | Child, 21 | ChildWithDoCheck, 22 | ], 23 | template: r''' 24 | 25 | 26 | ''', 27 | ) 28 | class GoldenComponent { 29 | String name = deopt('World'); 30 | } 31 | 32 | @Component( 33 | selector: 'child', 34 | template: 'Name: {{name}}', 35 | ) 36 | class Child { 37 | @Input() 38 | String? name; 39 | } 40 | 41 | @Component( 42 | selector: 'child-with-do-check', 43 | template: 'Name: {{name}}', 44 | ) 45 | class ChildWithDoCheck implements DoCheck { 46 | @Input() 47 | String? name; 48 | 49 | @override 50 | void ngDoCheck() {} 51 | } 52 | -------------------------------------------------------------------------------- /goldens/test/change_detection/directive_change_detector.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | library golden; 3 | 4 | import 'package:js/js.dart'; 5 | import 'package:ngdart/angular.dart'; 6 | 7 | import 'directive_change_detector.template.dart' as ng; 8 | 9 | /// Avoids Dart2JS thinking something is constant/unchanging. 10 | @JS() 11 | external T deopt([Object? any]); 12 | 13 | void main() { 14 | runApp(ng.createGoldenComponentFactory()); 15 | } 16 | 17 | @Component( 18 | selector: 'golden', 19 | directives: [ 20 | NgModelLike, 21 | ], 22 | template: r''' 23 | 24 | ''', 25 | ) 26 | class GoldenComponent { 27 | String value = deopt(); 28 | } 29 | 30 | @Directive( 31 | selector: '[ngModel]:not([ngControl]):not([ngFormControl])', 32 | ) 33 | class NgModelLike implements AfterChanges, OnInit { 34 | @Output('ngModelChange') 35 | Stream get modelChange => const Stream.empty(); 36 | 37 | @Input('ngModel') 38 | set model(Object ngModel) {} 39 | 40 | @override 41 | void ngAfterChanges() {} 42 | 43 | @override 44 | void ngOnInit() {} 45 | } 46 | -------------------------------------------------------------------------------- /goldens/test/change_detection/on_push.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | library golden; 3 | 4 | import 'package:js/js.dart'; 5 | import 'package:ngdart/angular.dart'; 6 | 7 | import 'on_push.template.dart' as ng; 8 | 9 | /// Avoids Dart2JS thinking something is constant/unchanging. 10 | @JS() 11 | external T deopt([Object? any]); 12 | 13 | void main() { 14 | runApp(ng.createGoldenComponentFactory()); 15 | } 16 | 17 | @Component( 18 | selector: 'golden', 19 | directives: [ 20 | Child, 21 | ChildWithDoCheck, 22 | ], 23 | template: r''' 24 | 25 | 26 | ''', 27 | changeDetection: ChangeDetectionStrategy.onPush, 28 | ) 29 | class GoldenComponent { 30 | String name = deopt(); 31 | } 32 | 33 | @Component( 34 | selector: 'child', 35 | template: 'Name: {{name}}', 36 | changeDetection: ChangeDetectionStrategy.onPush, 37 | ) 38 | class Child { 39 | @Input() 40 | String? name; 41 | } 42 | 43 | @Component( 44 | selector: 'child-with-do-check', 45 | template: 'Name: {{name}}', 46 | changeDetection: ChangeDetectionStrategy.onPush, 47 | ) 48 | class ChildWithDoCheck implements DoCheck { 49 | @Input() 50 | String? name; 51 | 52 | @override 53 | void ngDoCheck() {} 54 | } 55 | -------------------------------------------------------------------------------- /goldens/test/dependency_injection/visibility.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngdart/angular.dart'; 2 | 3 | import 'visibility.template.dart' as ng; 4 | 5 | void main() { 6 | runApp(ng.createGoldenComponentFactory()); 7 | } 8 | 9 | @Component( 10 | selector: 'golden', 11 | directives: [ 12 | HasVisibilityAll, 13 | HasVisibilityLocal, 14 | ], 15 | template: ''' 16 | 17 | 18 | ''', 19 | ) 20 | class GoldenComponent {} 21 | 22 | @Component( 23 | selector: 'has-visibility-all', 24 | template: '', 25 | visibility: Visibility.all, 26 | ) 27 | class HasVisibilityAll {} 28 | 29 | @Component( 30 | selector: 'has-visibility-local', 31 | template: '', 32 | ) 33 | class HasVisibilityLocal {} 34 | -------------------------------------------------------------------------------- /goldens/test/dom_bindings/html_properties.template.dart.golden: -------------------------------------------------------------------------------- 1 | // ************************************************************************** 2 | // Generator: AngularDart Compiler 3 | // ************************************************************************** 4 | 5 | import 'html_properties.dart'; 6 | -------------------------------------------------------------------------------- /goldens/test/language/null_safety.template.dart.golden: -------------------------------------------------------------------------------- 1 | // ************************************************************************** 2 | // Generator: AngularDart Compiler 3 | // ************************************************************************** 4 | 5 | import 'null_safety.dart'; 6 | -------------------------------------------------------------------------------- /goldens/test/lifecycle_hooks/after_changes.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | library golden; 3 | 4 | import 'package:js/js.dart'; 5 | import 'package:ngdart/angular.dart'; 6 | 7 | import 'after_changes.template.dart' as ng; 8 | 9 | /// Avoids Dart2JS thinking something is constant/unchanging. 10 | @JS() 11 | external T deopt([Object? any]); 12 | 13 | void main() { 14 | runApp(ng.createGoldenComponentFactory()); 15 | } 16 | 17 | @Component( 18 | selector: 'golden', 19 | directives: [UsesAfterChanges], 20 | template: '', 21 | ) 22 | class GoldenComponent { 23 | late String a; 24 | late String b; 25 | late String c; 26 | 27 | GoldenComponent() { 28 | deopt(() { 29 | a = deopt('a'); 30 | b = deopt('b'); 31 | c = deopt('c'); 32 | }); 33 | } 34 | } 35 | 36 | @Component( 37 | selector: 'uses-after-changes', 38 | template: '', 39 | ) 40 | class UsesAfterChanges implements AfterChanges { 41 | @Input() 42 | String? a; 43 | 44 | @Input() 45 | String? b; 46 | 47 | @Input() 48 | String? c; 49 | 50 | @override 51 | void ngAfterChanges() { 52 | deopt([a, b, c]); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /goldens/test/lifecycle_hooks/do_check.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | library golden; 3 | 4 | import 'package:js/js.dart'; 5 | import 'package:ngdart/angular.dart'; 6 | 7 | import 'do_check.template.dart' as ng; 8 | 9 | /// Avoids Dart2JS thinking something is constant/unchanging. 10 | @JS() 11 | external T deopt([Object? any]); 12 | 13 | void main() { 14 | runApp(ng.createGoldenComponentFactory()); 15 | } 16 | 17 | @Component( 18 | selector: 'golden', 19 | directives: [UsesDoCheck], 20 | template: '', 21 | ) 22 | class GoldenComponent { 23 | late String a; 24 | late String b; 25 | late String c; 26 | 27 | GoldenComponent() { 28 | deopt(() { 29 | a = deopt('a'); 30 | b = deopt('b'); 31 | c = deopt('c'); 32 | }); 33 | } 34 | } 35 | 36 | @Component( 37 | selector: 'uses-do-check', 38 | template: '', 39 | ) 40 | class UsesDoCheck implements DoCheck { 41 | @Input() 42 | String? a; 43 | 44 | @Input() 45 | String? b; 46 | 47 | @Input() 48 | String? c; 49 | 50 | @override 51 | void ngDoCheck() { 52 | deopt([a, b, c]); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /goldens/test/lifecycle_hooks/on_init_and_destroy.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | library golden; 3 | 4 | import 'package:js/js.dart'; 5 | import 'package:ngdart/angular.dart'; 6 | 7 | import 'on_init_and_destroy.template.dart' as ng; 8 | 9 | /// Avoids Dart2JS thinking something is constant/unchanging. 10 | @JS() 11 | external T deopt([Object? any]); 12 | 13 | void main() { 14 | runApp(ng.createGoldenComponentFactory()); 15 | } 16 | 17 | @Component( 18 | selector: 'golden', 19 | directives: [ 20 | UsesOnInit, 21 | UsesOnDestroy, 22 | ], 23 | template: ''' 24 | 25 | 26 | 27 | 28 | ''', 29 | ) 30 | class GoldenComponent { 31 | late String a; 32 | late String b; 33 | late String c; 34 | 35 | GoldenComponent() { 36 | deopt(() { 37 | a = deopt('a'); 38 | b = deopt('b'); 39 | c = deopt('c'); 40 | }); 41 | } 42 | } 43 | 44 | @Component( 45 | selector: 'uses-on-init', 46 | template: '', 47 | ) 48 | class UsesOnInit implements OnInit { 49 | @Input() 50 | String? a; 51 | 52 | @Input() 53 | String? b; 54 | 55 | @Input() 56 | String? c; 57 | 58 | @override 59 | void ngOnInit() { 60 | deopt([a, b, c]); 61 | } 62 | } 63 | 64 | @Component( 65 | selector: 'uses-on-destroy', 66 | template: '', 67 | ) 68 | class UsesOnDestroy implements OnDestroy { 69 | @Input() 70 | String? a; 71 | 72 | @Input() 73 | String? b; 74 | 75 | @Input() 76 | String? c; 77 | 78 | @override 79 | void ngOnDestroy() { 80 | deopt([a, b, c]); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /goldens/test/nnbd/hello_world.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngdart/angular.dart'; 2 | 3 | import 'hello_world.template.dart' as ng; 4 | 5 | void main() { 6 | runApp(ng.createHelloWorldComponentFactory()); 7 | } 8 | 9 | @Component( 10 | selector: 'hello-world', 11 | template: 'Hello World', 12 | ) 13 | class HelloWorldComponent {} 14 | -------------------------------------------------------------------------------- /goldens/test/templates/directive_star_syntax.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | library golden; 3 | 4 | import 'package:js/js.dart'; 5 | import 'package:ngdart/angular.dart'; 6 | 7 | import 'directive_star_syntax.template.dart' as ng; 8 | 9 | /// Avoids Dart2JS thinking something is constant/unchanging. 10 | @JS() 11 | external T deopt([Object? any]); 12 | 13 | void main() { 14 | runApp(ng.createGoldenComponentFactory()); 15 | } 16 | 17 | @Component( 18 | selector: 'golden', 19 | directives: [ 20 | NgFor, 21 | NgIf, 22 | ], 23 | template: ''' 24 |
25 | Show some {{value}}. 26 |
27 |
    28 |
  • 29 | {{index}}: {{v}} ({{odd}}) 30 |
  • 31 |
32 | ''', 33 | ) 34 | class GoldenComponent { 35 | bool show = deopt(); 36 | String value = deopt(); 37 | List values = deopt(); 38 | } 39 | -------------------------------------------------------------------------------- /goldens/test/templates/i18n.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngdart/angular.dart'; 2 | 3 | import 'i18n.template.dart' as ng; 4 | 5 | void main() { 6 | runApp(ng.createGoldenComponentFactory()); 7 | } 8 | 9 | @Component( 10 | selector: 'golden', 11 | directives: [ 12 | MessageDirective, 13 | ], 14 | template: ''' 15 | 16 |

22 | Message 23 |

24 | 25 | 26 | message 27 | 28 | 29 |

30 | This message
31 | contains multiple levels of nested HTML. 32 |

33 | 34 | 35 |
36 | ''', 37 | ) 38 | class GoldenComponent {} 39 | 40 | @Directive( 41 | selector: '[message]', 42 | ) 43 | class MessageDirective { 44 | @Input() 45 | String? message; 46 | } 47 | -------------------------------------------------------------------------------- /goldens/test/templates/nested_structural_directives.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | library golden; 3 | 4 | import 'package:js/js.dart'; 5 | import 'package:ngdart/angular.dart'; 6 | 7 | import 'nested_structural_directives.template.dart' as ng; 8 | 9 | /// Avoids Dart2JS thinking something is constant/unchanging. 10 | @JS() 11 | external T deopt([Object? any]); 12 | 13 | void main() { 14 | runApp(ng.createGoldenComponentFactory()); 15 | } 16 | 17 | @Component( 18 | selector: 'golden', 19 | directives: [ 20 | NgFor, 21 | NgIf, 22 | ], 23 | template: ''' 24 | 25 | 26 | 34 | 35 |
27 | 28 | Even: {{col}} 29 | 30 | 31 | Odd: {{col}} 32 | 33 |
36 | ''', 37 | ) 38 | class GoldenComponent { 39 | List> matrix = deopt(); 40 | } 41 | -------------------------------------------------------------------------------- /goldens/test/templates/type_inference.dart: -------------------------------------------------------------------------------- 1 | library golden; 2 | 3 | import 'package:ngdart/angular.dart'; 4 | 5 | import 'type_inference.template.dart' as ng; 6 | 7 | void main() { 8 | runApp(ng.createGoldenComponentFactory()); 9 | } 10 | 11 | @Component( 12 | selector: 'golden', 13 | directives: [NgFor], 14 | template: ''' 15 | 16 | {{stringA + stringB}} 17 | 18 | 19 | {{stringA.toUpperCase()}} 20 | 21 | 22 | {{max(int1, int2).isEven}} 23 | 24 | 25 | {{duration.inMilliseconds}} 26 | 27 | 28 | 29 | 30 | {{duration.inMilliseconds}} 31 | 32 | 33 | ''', 34 | ) 35 | class GoldenComponent { 36 | static T max(T a, T b) { 37 | return a.compareTo(b) < 0 ? b : a; 38 | } 39 | 40 | var stringA = '1'; 41 | var stringB = '2'; 42 | 43 | var int1 = 1; 44 | var int2 = 2; 45 | 46 | var durationList = [ 47 | Duration(seconds: 1), 48 | ]; 49 | 50 | var nestedLists = [ 51 | [ 52 | Duration(seconds: 1), 53 | ], 54 | ]; 55 | } 56 | -------------------------------------------------------------------------------- /goldens/test/templates/whitespace.dart: -------------------------------------------------------------------------------- 1 | @JS() 2 | library golden; 3 | 4 | import 'package:js/js.dart'; 5 | import 'package:ngdart/angular.dart'; 6 | 7 | import 'whitespace.template.dart' as ng; 8 | 9 | void main() { 10 | runApp(ng.createGoldenComponentFactory()); 11 | } 12 | 13 | @Component( 14 | selector: 'golden', 15 | directives: [ 16 | PreserveWhitespace, 17 | MinifyWhitespace, 18 | ], 19 | template: ''' 20 | 21 | 22 | ''', 23 | ) 24 | class GoldenComponent {} 25 | 26 | @Component( 27 | selector: 'preserve-whitespace-true', 28 | template: r''' 29 |
30 | Welcome... 31 | To... 32 | Jurassic... 33 | Park! 34 |
35 |
36 | Default i18n text 37 |
38 | ''', 39 | preserveWhitespace: true, 40 | ) 41 | class PreserveWhitespace {} 42 | 43 | @Component( 44 | selector: 'preserve-whitespace-false', 45 | template: r''' 46 |
47 | Welcome... 48 | To... 49 | Jurassic... 50 | Park! 51 |
52 |
53 | Default i18n text 54 |
55 | ''', 56 | ) 57 | class MinifyWhitespace {} 58 | -------------------------------------------------------------------------------- /goldens/tool/update.dart: -------------------------------------------------------------------------------- 1 | import 'package:glob/glob.dart'; 2 | import 'package:glob/list_local_fs.dart'; 3 | import 'package:path/path.dart' as path; 4 | 5 | const dartTool = '.dart_tool/build/generated/goldens'; 6 | const template = '$dartTool/test/**/*.template.dart'; 7 | const js = '$dartTool/test/**/*.js'; 8 | 9 | void main() { 10 | for (var entity in Glob(template).listSync()) { 11 | var relative = path.relative(entity.path, from: dartTool); 12 | entity.renameSync('$relative.golden'); 13 | } 14 | 15 | for (var entity in Glob(js).listSync()) { 16 | var relative = path.relative(entity.path, from: dartTool); 17 | entity.renameSync(relative.replaceAll('.dart.js', '.js.golden')); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /melos.yaml: -------------------------------------------------------------------------------- 1 | name: angular 2 | repository: https://github.com/angulardart-community/angular 3 | 4 | packages: 5 | - "**" 6 | # - ngast 7 | # - ngcompiler 8 | # - ngdart 9 | # - ngforms 10 | # - ngrouter 11 | # - ngtest 12 | 13 | ignore: 14 | - _tests 15 | - examples 16 | -------------------------------------------------------------------------------- /melos_angular.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /mono_repo.yaml: -------------------------------------------------------------------------------- 1 | github: 2 | on: 3 | push: 4 | branches: 5 | - master 6 | - google 7 | pull_request: 8 | branches: 9 | - master 10 | - google 11 | 12 | # on_completion: 13 | # - name: "Notify failure" 14 | # # Run only if other jobs have failed and this is a push build. 15 | # if: (github.event_name == 'push' || github.event_name == 'schedule') && failure() 16 | # runs-on: ubuntu-latest 17 | # steps: 18 | # - run: > 19 | # curl -H "Content-Type: application/json" -X POST -d \ 20 | # "{'text':'Build failed! ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}'}" \ 21 | # "${CHAT_WEBHOOK_URL}" 22 | # env: 23 | # CHAT_WEBHOOK_URL: ${{ secrets.TEAM_CHAT_WEBHOOK_URL }} 24 | 25 | self_validate: true 26 | merge_stages: 27 | - analyze 28 | -------------------------------------------------------------------------------- /ngast/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2014-2020 Dart Project Authors https://dart.dev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /ngast/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: ../analysis_options.yaml 2 | -------------------------------------------------------------------------------- /ngast/dart_test.yaml: -------------------------------------------------------------------------------- 1 | # Include common configuration. 2 | include: ../tool/dart_test_repo.yaml 3 | 4 | # This repository has only VM tests. 5 | platforms: 6 | - vm 7 | -------------------------------------------------------------------------------- /ngast/example/README.md: -------------------------------------------------------------------------------- 1 | Not intended for public use. Please see the 2 | [`ngdart`](https://pub.dev/packages/ngdart) package for more info on 3 | AngularDart. 4 | -------------------------------------------------------------------------------- /ngast/lib/angular_ast.dart: -------------------------------------------------------------------------------- 1 | export 'ngast.dart'; 2 | -------------------------------------------------------------------------------- /ngast/lib/src/ast.dart: -------------------------------------------------------------------------------- 1 | export 'ast/attribute.dart' show AttributeAst, ParsedAttributeAst; 2 | export 'ast/close_element.dart' show CloseElementAst, ParsedCloseElementAst; 3 | export 'ast/comment.dart' show CommentAst; 4 | export 'ast/container.dart' show ContainerAst; 5 | export 'ast/content.dart' show EmbeddedContentAst, ParsedEmbeddedContentAst; 6 | export 'ast/element.dart' show ElementAst, ParsedElementAst; 7 | export 'ast/event.dart' show EventAst, ParsedEventAst; 8 | export 'ast/interface.dart' 9 | show 10 | ParsedDecoratorAst, 11 | StandaloneTemplateAst, 12 | SyntheticTemplateAst, 13 | TagOffsetInfo, 14 | TemplateAst; 15 | export 'ast/interpolation.dart' show InterpolationAst, ParsedInterpolationAst; 16 | export 'ast/let_binding.dart' show LetBindingAst, ParsedLetBindingAst; 17 | export 'ast/property.dart' show PropertyAst, ParsedPropertyAst; 18 | export 'ast/reference.dart' show ReferenceAst, ParsedReferenceAst; 19 | export 'ast/sugar/annotation.dart' show AnnotationAst, ParsedAnnotationAst; 20 | export 'ast/sugar/banana.dart' show BananaAst, ParsedBananaAst; 21 | export 'ast/sugar/star.dart' show StarAst, ParsedStarAst; 22 | export 'ast/template.dart' show EmbeddedTemplateAst; 23 | export 'ast/text.dart' show TextAst; 24 | -------------------------------------------------------------------------------- /ngast/lib/src/exception_handler/angular_parser_exception.dart: -------------------------------------------------------------------------------- 1 | part of 'exception_handler.dart'; 2 | 3 | /// Exception class to be used in AngularAst parser. 4 | @sealed 5 | class AngularParserException extends Error { 6 | /// Length of error segment/token. 7 | final int? length; 8 | 9 | /// Reasoning for exception to be raised. 10 | final ParserErrorCode errorCode; 11 | 12 | /// Offset of where the exception was detected. 13 | final int? offset; 14 | 15 | AngularParserException( 16 | this.errorCode, 17 | this.offset, 18 | this.length, 19 | ); 20 | 21 | @override 22 | bool operator ==(Object other) { 23 | return other is AngularParserException && 24 | errorCode == other.errorCode && 25 | length == other.length && 26 | offset == other.offset; 27 | } 28 | 29 | @override 30 | int get hashCode => Object.hash(errorCode, length, offset); 31 | 32 | @override 33 | String toString() => 'AngularParserException{$errorCode}'; 34 | } 35 | -------------------------------------------------------------------------------- /ngast/lib/src/exception_handler/exception_handler.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart'; 2 | 3 | part 'angular_parser_exception.dart'; 4 | part 'exceptions.dart'; 5 | 6 | abstract class ExceptionHandler { 7 | void handle(AngularParserException? e); 8 | } 9 | 10 | @sealed 11 | class ThrowingExceptionHandler implements ExceptionHandler { 12 | @override 13 | void handle(AngularParserException? e) { 14 | if (e != null) { 15 | throw e; 16 | } 17 | } 18 | 19 | @literal 20 | const ThrowingExceptionHandler(); 21 | } 22 | 23 | class RecoveringExceptionHandler implements ExceptionHandler { 24 | final exceptions = []; 25 | 26 | @override 27 | void handle(AngularParserException? e) { 28 | if (e != null) { 29 | exceptions.add(e); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ngast/lib/src/expression/micro.dart: -------------------------------------------------------------------------------- 1 | import '../ast.dart'; 2 | import 'micro/ast.dart'; 3 | import 'micro/parser.dart'; 4 | 5 | export 'micro/ast.dart' show NgMicroAst; 6 | 7 | final _isBind = RegExp(r'\S+[:;]'); 8 | 9 | /// Returns whether [expression] is a special Angular *-star expression. 10 | /// 11 | /// This means it won't parse correctly with the standard expression parser, and 12 | /// [parseMicroExpression] is needed to de-sugar the expression into its 13 | /// multiple intents. 14 | bool isMicroExpression(String? expression) => 15 | expression != null && 16 | (expression.startsWith('let') || expression.startsWith(_isBind)); 17 | 18 | /// Returns a de-sugared micro AST from [expression]. 19 | NgMicroAst parseMicroExpression( 20 | String directive, 21 | String? expression, 22 | int? expressionOffset, { 23 | required String sourceUrl, 24 | TemplateAst? origin, 25 | }) => 26 | const NgMicroParser().parse( 27 | directive, 28 | expression, 29 | expressionOffset, 30 | sourceUrl: sourceUrl, 31 | origin: origin, 32 | ); 33 | -------------------------------------------------------------------------------- /ngast/lib/src/expression/micro/ast.dart: -------------------------------------------------------------------------------- 1 | import 'package:collection/collection.dart'; 2 | import 'package:meta/meta.dart'; 3 | 4 | import '../../ast.dart'; 5 | 6 | final _listEquals = const ListEquality(); 7 | 8 | /// A de-sugared form of longer pseudo expression. 9 | class NgMicroAst { 10 | /// What variable assignments were made. 11 | final List letBindings; 12 | 13 | /// What properties are bound. 14 | final List properties; 15 | 16 | @literal 17 | const NgMicroAst({ 18 | required this.letBindings, 19 | required this.properties, 20 | }); 21 | 22 | @override 23 | bool operator ==(Object other) { 24 | return other is NgMicroAst && 25 | _listEquals.equals(letBindings, other.letBindings) && 26 | _listEquals.equals(properties, other.properties); 27 | } 28 | 29 | @override 30 | int get hashCode { 31 | return Object.hash( 32 | _listEquals.hash(letBindings), _listEquals.hash(properties)); 33 | } 34 | 35 | @override 36 | String toString() => '#$NgMicroAst <$letBindings $properties>'; 37 | } 38 | -------------------------------------------------------------------------------- /ngast/lib/src/expression/micro/lexer.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart'; 2 | 3 | import 'scanner.dart'; 4 | import 'token.dart'; 5 | 6 | /// Separates an Angular micro-expression into a series of lexical tokens. 7 | class NgMicroLexer { 8 | @literal 9 | const factory NgMicroLexer() = NgMicroLexer._; 10 | 11 | // Prevent inheritance. 12 | const NgMicroLexer._(); 13 | 14 | /// Return a series of tokens by incrementally scanning [template]. 15 | Iterable tokenize(String template) sync* { 16 | var scanner = NgMicroScanner(template); 17 | var token = scanner.scan(); 18 | while (token != null) { 19 | yield token; 20 | token = scanner.scan(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ngast/lib/src/lexer.dart: -------------------------------------------------------------------------------- 1 | import 'package:meta/meta.dart'; 2 | 3 | import 'exception_handler/exception_handler.dart'; 4 | import 'scanner.dart'; 5 | import 'token/tokens.dart'; 6 | 7 | /// Separates an Angular template into a series of lexical tokens. 8 | /// 9 | /// ## Example use 10 | /// ```dart 11 | /// const NgLexer().tokenize('
Hello World!
'); 12 | /// ``` 13 | class NgLexer { 14 | @literal 15 | const factory NgLexer() = NgLexer._; 16 | 17 | // Prevent inheritance. 18 | const NgLexer._(); 19 | 20 | /// Return a series of tokens by incrementally scanning [template]. 21 | Iterable tokenize( 22 | String template, ExceptionHandler exceptionHandler) sync* { 23 | var scanner = NgScanner(template, exceptionHandler); 24 | var token = scanner.scan(); 25 | while (token != null) { 26 | yield token; 27 | token = scanner.scan(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ngast/lib/src/token/lexeme.dart: -------------------------------------------------------------------------------- 1 | part of 'tokens.dart'; 2 | 3 | /// A [NgSimpleToken] that has a custom lexeme, i.e. not predefined by type. 4 | /// 5 | /// For example, a `text` is (almost) any arbitrary string. 6 | class _LexemeNgSimpleToken extends NgSimpleToken { 7 | const _LexemeNgSimpleToken( 8 | int offset, this.lexeme, this.length, NgSimpleTokenType type) 9 | : super._(type, offset); 10 | 11 | @override 12 | bool operator ==(Object other) { 13 | return other is _LexemeNgSimpleToken && 14 | super == other && 15 | lexeme == other.lexeme; 16 | } 17 | 18 | @override 19 | int get hashCode => Object.hash(super.hashCode, lexeme); 20 | 21 | @override 22 | final String lexeme; 23 | 24 | @override 25 | final int length; 26 | } 27 | 28 | /// A [NgToken] that has a custom lexeme, i.e. not predefined by a token type. 29 | /// 30 | /// For example, an `elementIdentifier` is (almost) any arbitrary string. 31 | class _LexemeNgToken extends NgToken { 32 | const _LexemeNgToken( 33 | int offset, 34 | this.lexeme, 35 | NgTokenType type, { 36 | bool errorSynthetic = false, 37 | }) : super._( 38 | type, 39 | offset, 40 | errorSynthetic: errorSynthetic, 41 | ); 42 | 43 | @override 44 | bool operator ==(Object other) { 45 | return other is _LexemeNgToken && super == other && lexeme == other.lexeme; 46 | } 47 | 48 | @override 49 | int get hashCode => Object.hash(super.hashCode, lexeme); 50 | 51 | @override 52 | final String lexeme; 53 | } 54 | -------------------------------------------------------------------------------- /ngast/melos_ngast.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ngast/mono_pkg.yaml: -------------------------------------------------------------------------------- 1 | sdk: 2 | - pubspec 3 | - dev 4 | - stable 5 | 6 | stages: 7 | - analyze: 8 | - format: 9 | sdk: 10 | - pubspec 11 | - analyze: --fatal-infos . 12 | - unit_test: 13 | - test: -P ci 14 | 15 | cache: 16 | directories: 17 | - .dart_tool/build 18 | -------------------------------------------------------------------------------- /ngast/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: ngast 2 | description: Parser and utilities for AngularDart templates 3 | version: 3.0.0-dev.2 4 | repository: https://github.com/angulardart-community/angular 5 | 6 | environment: 7 | sdk: ">=3.6.0 <4.0.0" 8 | 9 | resolution: workspace 10 | 11 | dependencies: 12 | charcode: ^1.4.0 13 | collection: ^1.19.1 14 | meta: ^1.16.0 15 | source_span: ^1.10.1 16 | string_scanner: ^1.4.0 17 | 18 | dev_dependencies: 19 | lints: ^5.0.0 20 | path: ^1.9.1 21 | test: ^1.25.9 22 | -------------------------------------------------------------------------------- /ngast/test/ast_cli_tester.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:ngast/ngast.dart'; 4 | import 'package:path/path.dart' as p; 5 | 6 | RecoveringExceptionHandler exceptionHandler = RecoveringExceptionHandler(); 7 | 8 | List parse(String template) => const NgParser().parse( 9 | template, 10 | sourceUrl: '/test/parser_test.dart#inline', 11 | exceptionHandler: exceptionHandler, 12 | desugar: false, 13 | ); 14 | 15 | void main() { 16 | String input; 17 | exceptionHandler.exceptions.clear(); 18 | var fileDir = p.join('test', 'ast_cli_tester_source.html'); 19 | var file = File(fileDir.toString()); 20 | input = file.readAsStringSync(); 21 | //input = stdin.readLineSync(encoding: UTF8); 22 | var ast = parse(input); 23 | print('----------------------------------------------'); 24 | if (exceptionHandler is ThrowingExceptionHandler) { 25 | print('CORRECT!'); 26 | print(ast); 27 | } 28 | var exceptionsList = exceptionHandler.exceptions; 29 | if (exceptionsList.isEmpty) { 30 | print('CORRECT!'); 31 | print(ast); 32 | } else { 33 | var visitor = const HumanizingTemplateAstVisitor(); 34 | var fixed = ast.map((t) => t.accept(visitor)).join(''); 35 | print('ORGNL: $input'); 36 | print('FIXED: $fixed'); 37 | 38 | print('\n\nERRORS:'); 39 | for (var e in exceptionHandler.exceptions) { 40 | var context = input.substring(e.offset!, e.offset! + e.length!); 41 | print('${e.errorCode.message} :: $context at ${e.offset}'); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /ngast/test/ast_cli_tester_source.html: -------------------------------------------------------------------------------- 1 | 2 |

Showing {{items.length}} items:

3 |
  • 4 | {{x}} : {{item.trim()}} 5 |
  • 6 | 7 |
    8 |
    9 | {{ngForm.dirty}} 10 | 11 | 12 | 13 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ngast/test/cli_tester.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io'; 3 | 4 | import 'package:ngast/ngast.dart'; 5 | 6 | RecoveringExceptionHandler exceptionHandler = RecoveringExceptionHandler(); 7 | Iterable tokenize(String html) { 8 | exceptionHandler.exceptions.clear(); 9 | return const NgLexer().tokenize(html, exceptionHandler); 10 | } 11 | 12 | String untokenize(Iterable tokens) => tokens 13 | .fold(StringBuffer(), (buffer, token) => buffer..write(token.lexeme)) 14 | .toString(); 15 | 16 | void main() { 17 | String input; 18 | while (true) { 19 | input = stdin.readLineSync(encoding: utf8)!; 20 | if (input == 'QUIT') { 21 | break; 22 | } 23 | try { 24 | var tokens = tokenize(input); 25 | var fixed = untokenize(tokens); 26 | if (exceptionHandler.exceptions.isEmpty) { 27 | print('CORRECT(UNCHANGED): $input'); 28 | } else { 29 | print('ORGNL: $input'); 30 | print('FIXED: $fixed'); 31 | print('ERRORS:'); 32 | for (var e in exceptionHandler.exceptions) { 33 | var context = input.substring(e.offset!, e.offset! + e.length!); 34 | print('${e.errorCode.message} :: $context at ${e.offset}'); 35 | } 36 | } 37 | } catch (e) { 38 | print(e); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ngast/test/e2e/e2e_template_tests.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:ngast/ngast.dart'; 4 | import 'package:path/path.dart' as p; 5 | import 'package:test/test.dart'; 6 | 7 | void main() { 8 | var parse = const NgParser().parse; 9 | var templatesDir = p.join('test', 'e2e', 'templates'); 10 | 11 | // Just assert that we can parse all of these templates without failing. 12 | Directory(templatesDir).listSync().forEach((file) { 13 | if (file is File) { 14 | test('should parse ${p.basenameWithoutExtension(file.path)}', () { 15 | parse(file.readAsStringSync(), sourceUrl: file.absolute.path); 16 | }); 17 | } 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /ngast/test/e2e/templates/fixed_material_tab_strip.html: -------------------------------------------------------------------------------- 1 | 6 | 21 | -------------------------------------------------------------------------------- /ngast/test/e2e/templates/material_button.html: -------------------------------------------------------------------------------- 1 | 6 | 7 |
    8 | 9 |
    10 | 11 | 14 | 15 | -------------------------------------------------------------------------------- /ngast/test/e2e/templates/material_checkbox.html: -------------------------------------------------------------------------------- 1 | 6 |
    7 | 13 | 18 | 19 |
    20 |
    21 | {{label}} 22 | 23 |
    24 | -------------------------------------------------------------------------------- /ngast/test/e2e/templates/material_chip.html: -------------------------------------------------------------------------------- 1 | 6 |
    7 | {{label}} 8 | 9 |
    10 | 17 | 20 | -------------------------------------------------------------------------------- /ngast/test/e2e/templates/material_chips.html: -------------------------------------------------------------------------------- 1 | 6 |
    7 | 12 | 13 |
    14 | -------------------------------------------------------------------------------- /ngast/test/e2e/templates/material_dialog.html: -------------------------------------------------------------------------------- 1 | 6 | 7 |
    8 |
    9 | 10 |
    11 | 12 |
    {{error}}
    13 | 14 |
    18 | 19 |
    20 | 21 |
    22 | 23 |
    24 |
    25 |
    26 | -------------------------------------------------------------------------------- /ngast/test/e2e/templates/material_popup.html: -------------------------------------------------------------------------------- 1 | 6 | 34 | -------------------------------------------------------------------------------- /ngast/test/e2e/templates/material_progress.html: -------------------------------------------------------------------------------- 1 | 6 |
    13 |
    15 |
    17 |
    18 | -------------------------------------------------------------------------------- /ngast/test/e2e/templates/material_toggle.html: -------------------------------------------------------------------------------- 1 | 6 |
    19 |
    {{label}}
    20 |
    21 |
    22 |
    23 |
    24 | 25 |
    26 |
    27 |
    28 |
    29 | -------------------------------------------------------------------------------- /ngast/test/e2e/templates/scoreboard.html: -------------------------------------------------------------------------------- 1 | 6 |
    7 | 11 | 14 | 15 | 16 |
    17 | 18 |
    19 | 23 | 26 | 27 | 28 |
    29 | -------------------------------------------------------------------------------- /ngast/test/e2e/templates/scorecard.html: -------------------------------------------------------------------------------- 1 | 6 |
    7 | 11 | 14 | 15 | 16 |
    17 | 18 |
    19 | 23 | 26 | 27 | 28 |
    29 | -------------------------------------------------------------------------------- /ngast/test/visitor_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngast/ngast.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | // DesugarVisitor is tested by parser_test.dart 6 | var visitor = const HumanizingTemplateAstVisitor(); 7 | 8 | test('should humanize a simple template and preserve inner spaces', () { 9 | var templateString = ''; 10 | var template = parse( 11 | templateString, 12 | sourceUrl: '/test/visitor_test.dart#inline', 13 | ); 14 | expect( 15 | template.map((t) => t.accept(visitor)).join(''), 16 | equals(templateString), 17 | ); 18 | }); 19 | 20 | test('should humanize a simple template *with* de-sugaring applied', () { 21 | var template = parse( 22 | '', 23 | sourceUrl: '/test/visitor_test.dart#inline', 24 | desugar: true, 25 | ); 26 | expect( 27 | template.map((t) => t.accept(visitor)).join(''), 28 | equalsIgnoringWhitespace(r''' 29 | 30 | '''), 31 | ); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /ngcompiler/.pubignore: -------------------------------------------------------------------------------- 1 | pubspec_overrides.yaml 2 | -------------------------------------------------------------------------------- /ngcompiler/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017, the Dart project authors. All rights reserved. 2 | Redistribution and use in source and binary forms, with or without 3 | modification, are permitted provided that the following conditions are 4 | met: 5 | 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above 9 | copyright notice, this list of conditions and the following 10 | disclaimer in the documentation and/or other materials provided 11 | with the distribution. 12 | * Neither the name of Google Inc. nor the names of its 13 | contributors may be used to endorse or promote products derived 14 | from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /ngcompiler/README.md: -------------------------------------------------------------------------------- 1 | [![Pub Package](https://img.shields.io/pub/v/ngcompiler.svg)](https://pub.dev/packages/ngcompiler) 2 | [![Build Status](https://img.shields.io/github/actions/workflow/status/angulardart-community/angular/dart.yml?branch=master)](https://github.com/angulardart-community/angular/actions/workflows/dart.yml) 3 | [![Gitter](https://img.shields.io/gitter/room/angulardart/community)](https://gitter.im/angulardart/community) 4 | 5 | Tooling for compiling [AngularDart](https://pub.dev/packages/ngdart). 6 | -------------------------------------------------------------------------------- /ngcompiler/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: ../analysis_options.yaml 2 | 3 | analyzer: 4 | errors: 5 | implementation_imports: ignore 6 | -------------------------------------------------------------------------------- /ngcompiler/dart_test.yaml: -------------------------------------------------------------------------------- 1 | # Include common configuration. 2 | include: ../tool/dart_test_repo.yaml 3 | 4 | # This repository has only VM tests. 5 | platforms: 6 | - vm 7 | -------------------------------------------------------------------------------- /ngcompiler/example/README.md: -------------------------------------------------------------------------------- 1 | Not intended for public use. Please see the 2 | [`ngdart`](https://pub.dev/packages/ngdart) package for more info on 3 | AngularDart. 4 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/cli.dart: -------------------------------------------------------------------------------- 1 | /// Supports the compiler running in a command-line interface (CLI). 2 | /// 3 | /// Utilities and classes here are not directly related to the compilation 4 | /// pipeline, but instead are used to manage the process, logging, exception 5 | /// handling, and other related functionality. 6 | /// 7 | /// **NOTE**: This is not an externally stable API. Use at your own risk. 8 | @experimental 9 | library; 10 | 11 | import 'package:meta/meta.dart'; 12 | 13 | export 'src/angular_compiler/cli/builder.dart'; 14 | export 'src/angular_compiler/cli/flags.dart'; 15 | export 'src/angular_compiler/cli/logging.dart'; 16 | export 'src/angular_compiler/cli/messages.dart' 17 | show messages, SourceSpanMessageTuple; 18 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/angular_compiler/analyzer.dart: -------------------------------------------------------------------------------- 1 | export 'analyzer/common.dart'; 2 | export 'analyzer/di/dependencies.dart'; 3 | export 'analyzer/di/global_singleton_services.dart'; 4 | export 'analyzer/di/injector.dart'; 5 | export 'analyzer/di/modules.dart'; 6 | export 'analyzer/di/providers.dart'; 7 | export 'analyzer/di/tokens.dart'; 8 | export 'analyzer/link.dart'; 9 | export 'analyzer/types.dart'; 10 | export 'analyzer/view/directive.dart'; 11 | export 'analyzer/view/typed_reader.dart'; 12 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/angular_compiler/analyzer/di/global_singleton_services.dart: -------------------------------------------------------------------------------- 1 | import '../link.dart'; 2 | 3 | const _globalSingletonServices = [ 4 | TypeLink( 5 | 'ApplicationRef', 6 | 'asset:ngdart/lib/src/core/application_ref.dart', 7 | ), 8 | TypeLink( 9 | 'AppViewUtils', 10 | 'asset:ngdart/lib/src/core/linker/app_view_utils.dart', 11 | ), 12 | TypeLink( 13 | 'NgZone', 14 | 'asset:ngdart/lib/src/core/zone/ng_zone.dart', 15 | ), 16 | TypeLink( 17 | 'Testability', 18 | 'asset:ngdart/lib/src/testability/implementation.dart', 19 | ), 20 | ]; 21 | 22 | bool isGlobalSingletonService(TypeLink service) => 23 | _globalSingletonServices.contains(service); 24 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/angular_compiler/cli/messages/messages.dart: -------------------------------------------------------------------------------- 1 | import '../messages.dart'; 2 | 3 | /// URL of the AngularDart GitHub repository. 4 | const _github = 'https://github.com/angulardart-community/angular'; 5 | 6 | /// Concrete implementation of [Messages] for external users. 7 | class $Messages extends Messages { 8 | const $Messages() : super.base(); 9 | 10 | @override 11 | String get analysisFailureReasons => 12 | 'Try the following when diagnosing the problem:\n' 13 | ' * Check your IDE or with the dartanalyzer for errors or warnings\n' 14 | ' * Check your "import" statements for missing or incorrect URLs\n' 15 | '\n' 16 | 'If you are still stuck, file an issue and include this error message:\n' 17 | '$urlFileBugs'; 18 | 19 | @override 20 | final urlFileBugs = '$_github/issues/new'; 21 | 22 | @override 23 | String removeGlobalSingletonService(String service) => 24 | '"$service" is an app-wide, singleton service provided by the ' 25 | 'framework that cannot be overridden or manually provided.\n' 26 | '\n' 27 | 'If you are providing this service to fix a missing provider error, you ' 28 | "likely have created an injector that is disconnected from the app's " 29 | 'injector hierarchy. This can occur when instantiating an injector and ' 30 | 'you omit the parent injector argument, or explicitly configure an empty ' 31 | 'parent injector. Please check your injector constructors to make sure ' 32 | "the current context's injector is passed as the parent."; 33 | } 34 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/angular_compiler/emitter/split_dart_emitter.dart: -------------------------------------------------------------------------------- 1 | import 'package:code_builder/code_builder.dart'; 2 | 3 | // Unlike the default [DartEmitter], this has two output buffers, which is used 4 | // transitionally since other parts of the AngularDart compiler write code based 5 | // on the existing "Output AST" format (string-based). 6 | // 7 | // Once/if all code is using code_builder, this can be safely removed. 8 | class SplitDartEmitter extends DartEmitter { 9 | final StringSink? _writeImports; 10 | 11 | SplitDartEmitter( 12 | this._writeImports, { 13 | super.allocator, 14 | }) : super(orderDirectives: false, useNullSafetySyntax: true); 15 | 16 | @override 17 | StringSink visitDirective(Directive spec, [StringSink? output]) { 18 | // Always write import/export directives to a separate buffer. 19 | return super.visitDirective(spec, _writeImports); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/aria_attributes.dart: -------------------------------------------------------------------------------- 1 | // https://www.w3.org/TR/wai-aria-1.1/#state_prop_def 2 | const _ariaAttributes = { 3 | 'aria-activedescendant', 4 | 'aria-atomic', 5 | 'aria-autocomplete', 6 | 'aria-busy', 7 | 'aria-checked', 8 | 'aria-colcount', 9 | 'aria-colindex', 10 | 'aria-colspan', 11 | 'aria-controls', 12 | 'aria-current', 13 | 'aria-describedat', 14 | 'aria-describedby', 15 | 'aria-disabled', 16 | 'aria-dropeffect', 17 | 'aria-errormessage', 18 | 'aria-expanded', 19 | 'aria-flowto', 20 | 'aria-grabbed', 21 | 'aria-haspopup', 22 | 'aria-hidden', 23 | 'aria-invalid', 24 | 'aria-keyshortcuts', 25 | 'aria-label', 26 | 'aria-labelledby', 27 | 'aria-level', 28 | 'aria-live', 29 | 'aria-modal', 30 | 'aria-multiline', 31 | 'aria-multiselectable', 32 | 'aria-orientation', 33 | 'aria-owns', 34 | 'aria-placeholder', 35 | 'aria-posinset', 36 | 'aria-pressed', 37 | 'aria-readonly', 38 | 'aria-relevant', 39 | 'aria-required', 40 | 'aria-roledescription', 41 | 'aria-rowcount', 42 | 'aria-rowindex', 43 | 'aria-rowspan', 44 | 'aria-selected', 45 | 'aria-setsize', 46 | 'aria-sort', 47 | 'aria-valuemax', 48 | 'aria-valuemin', 49 | 'aria-valuenow', 50 | 'aria-valuetext' 51 | }; 52 | 53 | /// Returns true if input is a valid ARIA attribute. 54 | bool isAriaAttribute(String attribute) => _ariaAttributes.contains(attribute); 55 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/chars.dart: -------------------------------------------------------------------------------- 1 | const ngSpace = '\uE500'; 2 | 3 | String replaceNgSpace(String value) { 4 | return value.replaceAll(ngSpace, ' '); 5 | } 6 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/compiler_utils.dart: -------------------------------------------------------------------------------- 1 | import 'compile_metadata.dart'; 2 | 3 | const moduleSuffix = '.dart'; 4 | 5 | String templateModuleUrl(CompileTypeMetadata type) { 6 | var moduleUrl = type.moduleUrl!; 7 | var urlWithoutSuffix = 8 | moduleUrl.substring(0, moduleUrl.length - moduleSuffix.length); 9 | return '$urlWithoutSuffix.template$moduleSuffix'; 10 | } 11 | 12 | String stylesModuleUrl(String stylesheetUrl, bool shim) { 13 | return shim 14 | ? '$stylesheetUrl.shim$moduleSuffix' 15 | : '$stylesheetUrl$moduleSuffix'; 16 | } 17 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/html_tags.dart: -------------------------------------------------------------------------------- 1 | HtmlTagDefinition getHtmlTagDefinition(String tagName) { 2 | var result = _tagDefinitions[tagName.toLowerCase()]; 3 | return result ?? const HtmlTagDefinition(); 4 | } 5 | 6 | class HtmlTagDefinition { 7 | final String? implicitNamespacePrefix; 8 | final bool isVoid; 9 | 10 | const HtmlTagDefinition({this.implicitNamespacePrefix, this.isVoid = false}); 11 | } 12 | // see http://www.w3.org/TR/html51/syntax.html#optional-tags 13 | 14 | // This implementation does not fully conform to the HTML5 spec. 15 | const _tagDefinitions = { 16 | 'base': HtmlTagDefinition(isVoid: true), 17 | 'meta': HtmlTagDefinition(isVoid: true), 18 | 'area': HtmlTagDefinition(isVoid: true), 19 | 'embed': HtmlTagDefinition(isVoid: true), 20 | 'link': HtmlTagDefinition(isVoid: true), 21 | 'img': HtmlTagDefinition(isVoid: true), 22 | 'input': HtmlTagDefinition(isVoid: true), 23 | 'param': HtmlTagDefinition(isVoid: true), 24 | 'hr': HtmlTagDefinition(isVoid: true), 25 | 'br': HtmlTagDefinition(isVoid: true), 26 | 'source': HtmlTagDefinition(isVoid: true), 27 | 'track': HtmlTagDefinition(isVoid: true), 28 | 'wbr': HtmlTagDefinition(isVoid: true), 29 | 'col': HtmlTagDefinition(isVoid: true), 30 | 'svg': HtmlTagDefinition(implicitNamespacePrefix: 'svg'), 31 | 'math': HtmlTagDefinition(implicitNamespacePrefix: 'math'), 32 | }; 33 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/i18n/message.dart: -------------------------------------------------------------------------------- 1 | import 'package:collection/collection.dart'; 2 | 3 | import 'metadata.dart'; 4 | 5 | const _map = MapEquality(); 6 | 7 | /// An internationalized message. 8 | class I18nMessage { 9 | /// Arguments that appear as interpolations in [text]. 10 | /// 11 | /// These are currently only used to support HTML nested within this message. 12 | final Map args; 13 | 14 | /// Metadata used for internationalization of this message. 15 | final I18nMetadata metadata; 16 | 17 | /// The message text to be translated for different locales. 18 | final String text; 19 | 20 | /// Creates an internationalized message from [text] with [metadata]. 21 | /// 22 | /// Any arguments that appear as interpolations in [text] should be mapped 23 | /// to their value in [args]. 24 | I18nMessage( 25 | this.text, 26 | this.metadata, { 27 | this.args = const {}, 28 | }); 29 | 30 | /// Whether this message contains nested HTML. 31 | bool get containsHtml => args.isNotEmpty; 32 | 33 | @override 34 | int get hashCode => metadata.hashCode ^ text.hashCode ^ _map.hash(args); 35 | 36 | @override 37 | bool operator ==(Object other) => 38 | other is I18nMessage && 39 | other.metadata == metadata && 40 | other.text == text && 41 | _map.equals(other.args, args); 42 | } 43 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/js_split_facade.dart: -------------------------------------------------------------------------------- 1 | /// A [String.split] implementation that is like JS' implementation. 2 | /// 3 | /// See https://dartpad.dartlang.org/37a53b0d5d4cced6c7312b2b965ed7fd. 4 | List jsSplit(String s, RegExp regExp) { 5 | var parts = []; 6 | var lastEnd = 0; 7 | for (var match in regExp.allMatches(s)) { 8 | parts.add(s.substring(lastEnd, match.start)); 9 | lastEnd = match.end; 10 | for (var i = 0, len = match.groupCount; i < len; i++) { 11 | parts.add(match.group(i + 1)!); 12 | } 13 | } 14 | parts.add(s.substring(lastEnd)); 15 | return parts; 16 | } 17 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/optimize_ir/merge_events.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngcompiler/v1/src/compiler/ir/model.dart' as ir; 2 | 3 | /// Combines multiple [ir.EventHandlers] together as an optimization. 4 | /// 5 | /// In the case that multiple bindings on a directive or element target the same 6 | /// event name, we can merge these handlers into a single method. 7 | List mergeEvents(List events) { 8 | final visitedEvents = {}; 9 | for (var event in events) { 10 | var eventName = (event.target as ir.BoundEvent).name; 11 | var handler = visitedEvents[eventName]; 12 | if (handler == null) { 13 | visitedEvents[eventName] = event; 14 | continue; 15 | } 16 | visitedEvents[eventName] = _merge(handler, event); 17 | } 18 | return visitedEvents.values.toList(); 19 | } 20 | 21 | ir.Binding _merge(ir.Binding handler, ir.Binding event) => ir.Binding( 22 | target: handler.target, 23 | source: (handler.source as ir.EventHandler) 24 | .merge(event.source as ir.EventHandler)); 25 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/optimize_ir/optimize_lifecycles.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngcompiler/v1/src/compiler/ir/model.dart' as ir; 2 | 3 | /// Optimizes lifecycle hooks in the directive. 4 | /// 5 | /// If there are no inputs declared, then nothing can every change for the 6 | /// matched directive. Thus, we do not need to call the `ngAfterChanges` 7 | /// lifecycle hook. 8 | ir.MatchedDirective optimizeLifecycles(ir.MatchedDirective directive) { 9 | if (directive.inputs.isNotEmpty || 10 | !directive.hasLifecycle(ir.Lifecycle.afterChanges)) { 11 | return directive; 12 | } 13 | 14 | return ir.MatchedDirective( 15 | lifecycles: directive.lifecycles 16 | .where((lifecycle) => lifecycle != ir.Lifecycle.afterChanges) 17 | .toSet(), 18 | providerSource: directive.providerSource, 19 | inputs: directive.inputs, 20 | outputs: directive.outputs, 21 | hasInputs: directive.hasInputs, 22 | hasHostProperties: directive.hasHostProperties, 23 | isComponent: directive.isComponent, 24 | isOnPush: directive.isOnPush, 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/parse_util.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngast/ngast.dart'; 2 | import 'package:ngcompiler/v2/context.dart'; 3 | import 'package:source_span/source_span.dart'; 4 | 5 | /// Collects parsing exceptions from `ngast`, converting to [BuildError]. 6 | /// 7 | /// See [throwErrorsIfAny]. 8 | class AstExceptionHandler extends RecoveringExceptionHandler { 9 | /// Contents of the source file. 10 | final String _contents; 11 | 12 | /// URL to the source file. 13 | final String _sourceUrl; 14 | 15 | /// Directive that is being compiled. 16 | final String _directiveName; 17 | 18 | AstExceptionHandler( 19 | this._contents, 20 | this._sourceUrl, 21 | this._directiveName, 22 | ); 23 | 24 | /// Converts and throws [exceptions] as a [BuildError]. 25 | /// 26 | /// If no [exceptions] were collected during parsing no error is thrown. 27 | void throwErrorsIfAny() { 28 | if (exceptions.isEmpty) { 29 | return; 30 | } 31 | final sourceFile = SourceFile.fromString(_contents, url: _sourceUrl); 32 | throw BuildError.fromMultiple( 33 | exceptions.map( 34 | (e) => BuildError.forSourceSpan( 35 | sourceFile.span(e.offset!, e.offset! + e.length!), 36 | e.errorCode.message, 37 | ), 38 | ), 39 | 'Errors in $_sourceUrl while compiling component $_directiveName', 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/schema/element_schema_registry.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngcompiler/v1/src/compiler/security.dart'; 2 | 3 | abstract class ElementSchemaRegistry { 4 | bool hasProperty(String tagName, String propName); 5 | bool hasAttribute(String tagName, String attributeName); 6 | bool hasEvent(String tagName, String eventName); 7 | String getMappedPropName(String propName); 8 | TemplateSecurityContext securityContext(String tagName, String propName); 9 | } 10 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/security.dart: -------------------------------------------------------------------------------- 1 | /// A [TemplateSecurityContext] specifies a category of security vulnerabilities 2 | /// if the content is not sanitized. 3 | /// 4 | /// Examples: A DOM property that is used as a url is classified as having 5 | /// the Url [HtmlSecurityContext]. 6 | /// 7 | /// [innerHTML] that could cause Cross Site Scripting (XSS) security bugs when 8 | /// improperly handled is classified as HTML. 9 | enum TemplateSecurityContext { 10 | /// No security implication. 11 | none, 12 | 13 | /// Context for free form html content. 14 | html, 15 | 16 | /// Context for element style. 17 | style, 18 | 19 | /// Link such as a,href. 20 | url, 21 | 22 | /// Url pointing to a resource to be loaded. 23 | resourceUrl, 24 | } 25 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/source_module.dart: -------------------------------------------------------------------------------- 1 | /// [outputUrl] and the generated [sourceCode] related to view compilation. 2 | class DartSourceOutput { 3 | final String outputUrl; 4 | final String sourceCode; 5 | 6 | DartSourceOutput({ 7 | required this.outputUrl, 8 | required this.sourceCode, 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/style_url_resolver.dart: -------------------------------------------------------------------------------- 1 | class StyleWithImports { 2 | final String style; 3 | final List styleUrls; 4 | StyleWithImports(this.style, this.styleUrls); 5 | } 6 | 7 | /// Whether [url] resides within the current package or a dependency. 8 | bool isStyleUrlResolvable(String? url) { 9 | if (url == null || url.isEmpty || url[0] == '/') return false; 10 | var schemeMatch = _urlWithSchemaRe.firstMatch(url); 11 | return schemeMatch == null || 12 | schemeMatch[1] == 'package' || 13 | schemeMatch[1] == 'asset'; 14 | } 15 | 16 | /// Rewrites style sheets by resolving and removing the @import urls that 17 | /// are either relative or don't have a `package:` scheme 18 | StyleWithImports extractStyleUrls(String baseUrl, String cssText) { 19 | Uri? baseUri; 20 | var foundUrls = []; 21 | var modifiedCssText = cssText.replaceAllMapped(_cssImportRe, (m) { 22 | var url = m[1] ?? m[2]; 23 | if (!isStyleUrlResolvable(url)) { 24 | // Do not attempt to resolve non-package absolute URLs with URI scheme 25 | return m[0]!; 26 | } 27 | baseUri ??= Uri.parse(baseUrl); 28 | foundUrls.add(baseUri!.resolve(url!).toString()); 29 | return ''; 30 | }); 31 | return StyleWithImports(modifiedCssText, foundUrls); 32 | } 33 | 34 | final _cssImportRe = RegExp(r'@import\s+(?:url\()?\s*(?:(?:[' 35 | "'" 36 | r'"]([^' 37 | "'" 38 | r'"]*))|([^;\)\s]*))[^;]*;?'); 39 | final _urlWithSchemaRe = RegExp('^([^:/?#]+):'); 40 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/stylesheet_compiler/builder.dart: -------------------------------------------------------------------------------- 1 | import 'package:build/build.dart'; 2 | import 'package:ngcompiler/v1/cli.dart'; 3 | 4 | import 'processor.dart'; 5 | 6 | const _cssExtension = '.css'; 7 | const _shimmedStylesheetExtension = '.css.shim.dart'; 8 | const _nonShimmedStylesheetExtension = '.css.dart'; 9 | 10 | /// Pre-compiles CSS stylesheet files to Dart code for Angular 2. 11 | class StylesheetCompiler implements Builder { 12 | final CompilerFlags _flags; 13 | 14 | const StylesheetCompiler(this._flags); 15 | 16 | @override 17 | final buildExtensions = const { 18 | _cssExtension: [ 19 | _shimmedStylesheetExtension, 20 | _nonShimmedStylesheetExtension, 21 | ], 22 | }; 23 | 24 | @override 25 | Future build(BuildStep buildStep) async { 26 | final outputs = await processStylesheet( 27 | buildStep, 28 | buildStep.inputId, 29 | _flags, 30 | ); 31 | outputs.forEach(buildStep.writeAsString); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/stylesheet_compiler/processor.dart: -------------------------------------------------------------------------------- 1 | import 'package:build/build.dart'; 2 | import 'package:ngcompiler/v1/cli.dart'; 3 | import 'package:ngcompiler/v1/src/compiler/module/ng_compiler_module.dart'; 4 | import 'package:ngcompiler/v1/src/compiler/source_module.dart'; 5 | import 'package:ngcompiler/v1/src/source_gen/common/url_resolver.dart'; 6 | 7 | Future> processStylesheet( 8 | BuildStep buildStep, 9 | AssetId stylesheetId, 10 | CompilerFlags flags, 11 | ) async { 12 | final stylesheetUrl = toAssetUri(stylesheetId); 13 | final templateCompiler = createViewCompiler(buildStep, flags); 14 | final cssText = await buildStep.readAsString(stylesheetId); 15 | final sourceModules = templateCompiler.compileStylesheet( 16 | stylesheetUrl, 17 | cssText, 18 | ); 19 | return _mapSourceByAssetId(sourceModules); 20 | } 21 | 22 | Map _mapSourceByAssetId(List modules) { 23 | final sourceByAssetId = {}; 24 | for (final module in modules) { 25 | final assetId = AssetId.resolve(Uri.parse(module.outputUrl)); 26 | sourceByAssetId[assetId] = module.sourceCode; 27 | } 28 | return sourceByAssetId; 29 | } 30 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/view_compiler/devtools.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngcompiler/v1/src/compiler/identifiers.dart'; 2 | import 'package:ngcompiler/v1/src/compiler/ir/model.dart'; 3 | import 'package:ngcompiler/v1/src/compiler/output/output_ast.dart'; 4 | 5 | /// Optionally returns a statement that records a [binding] for developer tools. 6 | /// 7 | /// If [binding] is an `@Input()` binding, this returns an `if` statement that 8 | /// records the bound [value] for inspection when developer tooling is enabled: 9 | /// 10 | /// ``` 11 | /// if (isDevToolsEnabled) { 12 | /// ComponentInspector.instance.recordInput(component, 'name', value); 13 | /// } 14 | /// ``` 15 | /// 16 | /// Otherwise, this returns null. 17 | Statement? devToolsBindingStatement( 18 | Binding binding, 19 | Expression? receiver, 20 | Expression value, 21 | ) { 22 | var target = binding.target; 23 | if (target is InputBinding) { 24 | return IfStmt(importExpr(DevTools.isDevToolsEnabled), [ 25 | _recordInputStatement(receiver!, literal(target.templateName), value), 26 | ]); 27 | } 28 | 29 | return null; 30 | } 31 | 32 | /// Returns a statement that records an input binding. 33 | /// 34 | /// ``` 35 | /// ComponentInspector.instance.recordInput(component, name, value); 36 | /// ``` 37 | Statement _recordInputStatement( 38 | Expression component, 39 | Expression name, 40 | Expression value, 41 | ) { 42 | return importExpr(DevTools.inspector) 43 | .callMethod('recordInput', [component, name, value]).toStmt(); 44 | } 45 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/view_compiler/event_binder.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngcompiler/v1/src/compiler/ir/model.dart' as ir; 2 | import 'package:ngcompiler/v1/src/compiler/view_compiler/bound_value_converter.dart' 3 | show BoundValueConverter; 4 | import 'package:ngcompiler/v1/src/compiler/view_compiler/ir/provider_source.dart'; 5 | 6 | import 'compile_element.dart' show CompileElement; 7 | 8 | void bindDirectiveOutputs( 9 | List outputs, 10 | ProviderSource directiveInstance, 11 | CompileElement compileElement, 12 | ) { 13 | var view = compileElement.view!; 14 | var converter = BoundValueConverter.forView(view); 15 | for (var output in outputs) { 16 | var handlerExpr = converter 17 | .scopeNamespace() 18 | .convertSourceToExpression(output.source, output.target.type)!; 19 | var nodeReference = view.createSubscription(); 20 | view.addEventListener( 21 | nodeReference, output, handlerExpr, directiveInstance.build()); 22 | } 23 | } 24 | 25 | void bindRenderOutputs( 26 | List outputs, CompileElement compileElement) { 27 | var converter = BoundValueConverter.forView(compileElement.view!); 28 | for (var output in outputs) { 29 | var handlerExpr = converter 30 | .scopeNamespace() 31 | .convertSourceToExpression(output.source, output.target.type)!; 32 | compileElement.view! 33 | .addEventListener(compileElement.renderNode, output, handlerExpr); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/view_compiler/interpolation_utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngcompiler/v1/src/compiler/expression_parser/ast.dart' as ast; 2 | import 'package:ngcompiler/v1/src/compiler/ir/model.dart' as ir; 3 | 4 | bool isInterpolation(ir.BindingSource? source) => 5 | source is ir.BoundExpression && source.expression.ast is ast.Interpolation; 6 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/view_compiler/ir/provider_source.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngcompiler/v1/src/compiler/compile_metadata.dart'; 2 | import 'package:ngcompiler/v1/src/compiler/output/output_ast.dart' as o; 3 | 4 | /// Provider interface passed to view compiler backends to generate code 5 | /// to instantiate a provider and consume. 6 | /// 7 | /// This allows us to hide the hierarchical nature of provider lookups and 8 | /// the actual resolution from view compiler backend. 9 | abstract class ProviderSource { 10 | final CompileTokenMetadata? token; 11 | 12 | ProviderSource(this.token); 13 | 14 | /// Returns a reference to this provider instance. 15 | o.Expression build(); 16 | 17 | /// Returns a reference to this provider's `ChangeDetectorRef`, if necessary. 18 | /// 19 | /// Returns a non-null result only if this provider instance is a component 20 | /// that uses `ChangeDetectionStrategy.onPush`. This result is used to 21 | /// implement `ChangeDetectorRef.markChildForCheck()`. 22 | /// 23 | /// Returns null otherwise. 24 | o.Expression? buildChangeDetectorRef() => null; 25 | 26 | /// Whether a dynamic `injectorGet(...)` is required to resolve this provider. 27 | /// 28 | /// For example: 29 | /// ```dart 30 | /// // DependencyService is dynamically required to resolve MyService. 31 | /// _MyService = MyService(injectorGet(DependencyService)); 32 | /// ``` 33 | bool get hasDynamicDependencies => false; 34 | } 35 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/view_compiler/ir/view_storage.dart: -------------------------------------------------------------------------------- 1 | import 'package:ngcompiler/v1/src/compiler/output/output_ast.dart' as o; 2 | 3 | /// Interface implemented by compiler backend to provide persistant storage 4 | /// of instances for AppView. 5 | abstract class ViewStorage { 6 | ViewStorageItem allocate( 7 | String name, { 8 | o.OutputType outputType = o.objectType, 9 | required List modifiers, 10 | o.Expression? initializer, 11 | }); 12 | 13 | o.Expression buildWriteExpr(ViewStorageItem item, o.Expression value); 14 | o.Expression buildReadExpr(ViewStorageItem item); 15 | } 16 | 17 | class ViewStorageItem { 18 | final String name; 19 | final o.OutputType? outputType; 20 | final List modifiers; 21 | final o.Expression? initializer; 22 | ViewStorageItem(this.name, 23 | {this.outputType, required this.modifiers, this.initializer}); 24 | 25 | bool get isStatic => modifiers.contains(o.StmtModifier.staticStmt); 26 | } 27 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/view_compiler/parse_utils.dart: -------------------------------------------------------------------------------- 1 | import '../expression_parser/ast.dart' 2 | show AST, ImplicitReceiver, MethodCall, PropertyRead; 3 | import 'constants.dart'; 4 | 5 | enum HandlerType { simpleNoArgs, simpleOneArg, notSimple } 6 | 7 | /// Classifies this event binding by it's form. 8 | /// 9 | /// The simple form looks like 10 | /// 11 | /// (event)="handler($event)" 12 | /// 13 | /// or 14 | /// 15 | /// (event)="handler()" 16 | /// 17 | /// Since these types of handlers are so common, we can optimize the code 18 | /// generated for them. 19 | HandlerType handlerTypeFromExpression(AST handler) { 20 | var eventHandler = handler; 21 | if (eventHandler is! MethodCall) { 22 | return HandlerType.notSimple; 23 | } 24 | var call = eventHandler; 25 | if (call.receiver is! ImplicitReceiver || call.namedArgs.isNotEmpty) { 26 | return HandlerType.notSimple; 27 | } 28 | if (call.args.isEmpty) { 29 | return HandlerType.simpleNoArgs; 30 | } 31 | if (call.args.length != 1) { 32 | return HandlerType.notSimple; 33 | } 34 | var singleArg = call.args.single; 35 | if (singleArg is! PropertyRead) { 36 | return HandlerType.notSimple; 37 | } 38 | var property = singleArg; 39 | if (property.name == EventHandlerVars.event.name && 40 | property.receiver is ImplicitReceiver) { 41 | return HandlerType.simpleOneArg; 42 | } else { 43 | return HandlerType.notSimple; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /ngcompiler/lib/v1/src/compiler/view_type.dart: -------------------------------------------------------------------------------- 1 | /// What type of generated `AppView` an instance is. 2 | enum ViewType { 3 | /// A view that contains the host element with bound component directive. 4 | /// 5 | /// Contains a `@Component`'s root element. 6 | host, 7 | 8 | /// The view of `@Component` that contains 0 to n _embedded_ views. 9 | component, 10 | 11 | /// A view that is embedded into another view via a `