Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#3 Signal inputs #53808

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
fb4c99a
refactor(compiler-cli): improve type safety of linker AST
devversion Dec 5, 2023
4fc484d
build: fix partial output generation errors swallowed
devversion Dec 5, 2023
a6265eb
refactor(core): add internal signal input support for `@Input` decorator
devversion Dec 14, 2023
30bac74
refactor(core): detect signal input transforms independently of flag
devversion Jan 9, 2024
b58b71d
refactor(core): properly emit input flags using bitwise or
devversion Jan 8, 2024
8df328e
refactor(compiler-cli): support linking/parsing new partial output fo…
devversion Dec 5, 2023
01e39e0
test: add signal input compliance tests for linking, partial output a…
devversion Dec 5, 2023
511ed8f
test: add integration test for signal inputs in CLI
devversion Dec 7, 2023
b2cd1be
refactor(core): improve error message and add guide for required inputs
devversion Dec 8, 2023
0333c07
test(core): add runtime tests for input signal
devversion Dec 8, 2023
69957aa
test(core): add test playground for zone signal inputs
devversion Nov 20, 2023
91eff2a
test(compiler-cli): add additional diagnostic test for generic inline…
devversion Dec 12, 2023
0f1dadd
refactor(compiler-cli): expose helper for parsing signal input class …
devversion Dec 14, 2023
3dba496
refactor(compiler-cli): expose import manager import insertion helper
devversion Dec 14, 2023
652ad3a
refactor(compiler-cli): add transform to support signal input in JIT
devversion Dec 14, 2023
3411a4b
refactor(compiler-cli): follow-up typo fixes for typecheck utilities
devversion Dec 14, 2023
acc4635
test: add completion tests for language service with signal inputs
devversion Jan 8, 2024
6ffb010
refactor(compiler-cli): diagnostics ensuring signal inputs are declar…
devversion Jan 8, 2024
697c985
refactor(compiler-cli): add diagnostic for inputs declared on static …
devversion Jan 8, 2024
01a3cc2
refactor(compiler-cli): drop dependency on external modules for input…
devversion Jan 8, 2024
4a11851
test: add infrastructure to run signal acceptance tests with JIT and AOT
devversion Jan 8, 2024
0271e1c
test(core): add acceptance unit tests for signal inputs
devversion Jan 8, 2024
1591df7
fixup! test: add integration test for signal inputs in CLI
devversion Jan 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .bazelignore
Expand Up @@ -16,6 +16,7 @@ integration/cli-hello-world/node_modules
integration/cli-hello-world-ivy-i18n/node_modules
integration/cli-hello-world-lazy/node_modules
integration/cli-hello-world-mocha/node_modules
integration/cli-signal-inputs/node_modules
integration/defer/node_modules
integration/dynamic-compiler/node_modules
integration/forms/node_modules
Expand Down
16 changes: 16 additions & 0 deletions adev/src/content/reference/errors/NG0950.md
@@ -0,0 +1,16 @@
# Required input is accessed before a value is set.

@description
A required input was accessed but no value was bound.

This can happen when a required input is accessed too early in your directive or component.
This is commonly happening when the input is read as part of class construction.

Inputs are guaranteed to be available in the `ngOnInit` lifecycle hook and afterwards.

## Fixing the error

Access the required input in reactive contexts.
For example, in the template itself, inside a `computed`, or inside an effect.

Alternatively, access the input inside the `ngOnInit` lifecycle hook, or later.
18 changes: 18 additions & 0 deletions aio/content/errors/NG0950.md
@@ -0,0 +1,18 @@
@name Input is required but no value is available yet.
@category runtime
@shortDescription A required input is accessed before a value is set.

@description
A required input was accessed but no value was bound.

This can happen when a required input is accessed too early in your directive or component.
This is commonly happening when the input is read as part of class construction.

Inputs are guaranteed to be available in the `ngOnInit` lifecycle hook and afterwards.

## Fixing the error

Access the required input in reactive contexts.
For example, in the template itself, inside a `computed`, or inside an effect.

Alternatively, access the input inside the `ngOnInit` lifecycle hook, or later.
3 changes: 3 additions & 0 deletions goldens/public-api/compiler-cli/error_code.md
Expand Up @@ -54,6 +54,7 @@ export enum ErrorCode {
INJECTABLE_INHERITS_INVALID_CONSTRUCTOR = 2016,
INLINE_TCB_REQUIRED = 8900,
INLINE_TYPE_CTOR_REQUIRED = 8901,
INPUT_DECLARED_ON_STATIC_MEMBER = 1100,
INTERPOLATED_SIGNAL_NOT_INVOKED = 8109,
INVALID_BANANA_IN_BOX = 8101,
LOCAL_COMPILATION_IMPORTED_STYLES_STRING = 11002,
Expand All @@ -80,6 +81,8 @@ export enum ErrorCode {
PIPE_MISSING_NAME = 2002,
SCHEMA_INVALID_ATTRIBUTE = 8002,
SCHEMA_INVALID_ELEMENT = 8001,
SIGNAL_INPUT_AND_DISALLOWED_DECORATOR = 1050,
SIGNAL_INPUT_AND_INPUTS_ARRAY_COLLISION = 1051,
SKIP_HYDRATION_NOT_STATIC = 8108,
SPLIT_TWO_WAY_BINDING = 8007,
SUFFIX_NOT_SUPPORTED = 8106,
Expand Down
2 changes: 2 additions & 0 deletions goldens/public-api/core/errors.md
Expand Up @@ -121,6 +121,8 @@ export const enum RuntimeErrorCode {
// (undocumented)
REQUIRE_SYNC_WITHOUT_SYNC_EMIT = 601,
// (undocumented)
REQUIRED_INPUT_NO_VALUE = -950,
// (undocumented)
RUNTIME_DEPS_INVALID_IMPORTED_TYPE = 1000,
// (undocumented)
RUNTIME_DEPS_ORPHAN_COMPONENT = 1001,
Expand Down
9 changes: 3 additions & 6 deletions integration/cli-hello-world/src/app/app.component.ts
@@ -1,10 +1,7 @@
import { Component } from '@angular/core';
import {Component} from '@angular/core';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
@Component(
{selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css']})
export class AppComponent {
title = 'cli-hello-world';
}
12 changes: 3 additions & 9 deletions integration/cli-hello-world/tsconfig.json
Expand Up @@ -11,16 +11,10 @@
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
"typeRoots": ["node_modules/@types"],
"lib": ["es2018", "dom"]
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
"strictTemplates": true
}
}
13 changes: 13 additions & 0 deletions integration/cli-signal-inputs/.editorconfig
@@ -0,0 +1,13 @@
# Editor configuration, see https://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
max_line_length = off
trim_trailing_whitespace = false
46 changes: 46 additions & 0 deletions integration/cli-signal-inputs/.gitignore
@@ -0,0 +1,46 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.

# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out

# dependencies
/node_modules

# profiling files
chrome-profiler-events*.json
speed-measure-plugin*.json

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*

# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings

# System Files
.DS_Store
Thumbs.db
6 changes: 6 additions & 0 deletions integration/cli-signal-inputs/BUILD.bazel
@@ -0,0 +1,6 @@
load("//integration:index.bzl", "ng_integration_test")

ng_integration_test(
name = "test",
setup_chromium = True,
)
27 changes: 27 additions & 0 deletions integration/cli-signal-inputs/README.md
@@ -0,0 +1,27 @@
# CliHelloWorld

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.0.0-next.9.

## Development server

Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.

## Code scaffolding

Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.

## Build

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.

## Running unit tests

Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Running end-to-end tests

Run `ng e2e` to execute the end-to-end tests via [Protractor](https://www.protractortest.org/).

## Further help

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/main/README.md).
117 changes: 117 additions & 0 deletions integration/cli-signal-inputs/angular.json
@@ -0,0 +1,117 @@
{
devversion marked this conversation as resolved.
Show resolved Hide resolved
"$schema": "../../node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"cli-signal-inputs": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.css"],
"scripts": [],
"optimization": true,
"progress": false
},
"configurations": {
"development": {
"sourceMap": true,
"optimization": false,
"extractLicenses": false
},
"production": {
"outputHashing": "all",
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"buildTarget": "cli-signal-inputs:build"
},
"configurations": {
"dev": {
"buildTarget": "cli-signal-inputs:build:dev"
},
"production": {
"buildTarget": "cli-signal-inputs:build:production"
},
"ci": {},
"ci-production": {
"buildTarget": "cli-signal-inputs:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "cli-signal-inputs:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": ["zone.js", "zone.js/testing"],
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.css"],
"scripts": [],
"progress": false,
"watch": false
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": ["tsconfig.app.json", "tsconfig.spec.json", "e2e/tsconfig.json"],
"exclude": ["**/node_modules/**"]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "cli-signal-inputs:serve",
"webdriverUpdate": false
},
"configurations": {
"production": {
"devServerTarget": "cli-signal-inputs:serve:production"
},
"ci": {
"devServerTarget": "cli-signal-inputs:serve:ci"
},
"ci-production": {
"devServerTarget": "cli-signal-inputs:serve:ci-production"
}
}
}
}
}
}
}
37 changes: 37 additions & 0 deletions integration/cli-signal-inputs/e2e/protractor.conf.js
@@ -0,0 +1,37 @@
// @ts-check
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts

Check notice on line 3 in integration/cli-signal-inputs/e2e/protractor.conf.js

View check run for this annotation

In Solidarity / Inclusive Language

Match Found

Please consider an alternative to `master`. Possibilities include: `primary`, `main`, `leader`, `active`, `writer`
Raw output
/master/gi
const { SpecReporter } = require('jasmine-spec-reporter');

/**
* @type { import("protractor").Config }
*/
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
chromeDriver: process.env.CHROMEDRIVER_BIN,
capabilities: {
browserName: 'chrome',
chromeOptions: {
binary: process.env.CHROME_BIN,
// See /integration/README.md#browser-tests for more info on these args
args: ['--no-sandbox', '--headless', '--disable-gpu', '--disable-dev-shm-usage', '--hide-scrollbars', '--mute-audio']
},
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
34 changes: 34 additions & 0 deletions integration/cli-signal-inputs/e2e/src/app.e2e-spec.ts
@@ -0,0 +1,34 @@
import {browser, logging} from 'protractor';

import {AppPage} from './app.po';

describe('cli-signal-inputs App', () => {
let page: AppPage;

beforeEach(() => {
page = new AppPage();
});

it('should show greet message', () => {
page.navigateTo();
expect(page.getGreetText()).toEqual('John - transformed-fallback');
expect(page.getUnboundLastNameGreetText()).toEqual('John - initial-unset');
});

it('should update greet message when last name is set', () => {
page.navigateTo();
expect(page.getGreetText()).toEqual('John - transformed-fallback');
page.setLastName();
expect(page.getGreetText()).toEqual('John - ng-Doe');
page.unsetLastName();
expect(page.getGreetText()).toEqual('John - transformed-fallback');
});

afterEach(async () => {
// Assert that there are no errors emitted from the browser
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
expect(logs).not.toContain(jasmine.objectContaining({
level: logging.Level.SEVERE,
} as logging.Entry));
});
});