mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
fix(compiler): inputs/outputs incorrectly parsed in jit mode (#46813)
The `Directive` and `Component` decorators support `inputs` and `outputs` fields which accept an array in the format of `"someInput"` or `"someInput: someAlias"`, however the parsing during JIT compilation was splitting on commas, not on colons, which resulted in incorrect parsing. E.g. `inputs: ["someInput: someAlias"]` was being parsed into `{"someInput: someAlias": "someInput: someAlias"}` instead of `{someInput: "someAlias"}`.
The feature was working by accident, because there's some logic further down in the compiler pipeline that was splitting the strings again.
PR Close #46813
This commit is contained in:
parent
7e03fc90d6
commit
f67d2cabaf
3 changed files with 20 additions and 16 deletions
|
|
@ -637,10 +637,10 @@ function isOutput(value: any): value is Output {
|
|||
}
|
||||
|
||||
function parseInputOutputs(values: string[]): StringMap {
|
||||
return values.reduce((map, value) => {
|
||||
const [field, property] = value.split(',').map(piece => piece.trim());
|
||||
map[field] = property || field;
|
||||
return map;
|
||||
return values.reduce((results, value) => {
|
||||
const [field, property] = value.split(':', 2).map(str => str.trim());
|
||||
results[field] = property || field;
|
||||
return results;
|
||||
}, {} as StringMap);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,6 @@ function mapToExpression(
|
|||
map: {[key: string]: string|string[]}, keepDeclared?: boolean): o.Expression {
|
||||
return o.literalMap(Object.getOwnPropertyNames(map).map(key => {
|
||||
// canonical syntax: `dirProp: publicProp`
|
||||
// if there is no `:`, use dirProp = elProp
|
||||
const value = map[key];
|
||||
let declaredName: string;
|
||||
let publicName: string;
|
||||
|
|
@ -186,12 +185,9 @@ function mapToExpression(
|
|||
minifiedName = key;
|
||||
needsDeclaredName = publicName !== declaredName;
|
||||
} else {
|
||||
[declaredName, publicName] = splitAtColon(key, [key, value]);
|
||||
minifiedName = declaredName;
|
||||
// Only include the declared name if extracted from the key, i.e. the key contains a colon.
|
||||
// Otherwise the declared name should be omitted even if it is different from the public name,
|
||||
// as it may have already been minified.
|
||||
needsDeclaredName = publicName !== declaredName && key.includes(':');
|
||||
minifiedName = declaredName = key;
|
||||
publicName = value;
|
||||
needsDeclaredName = false;
|
||||
}
|
||||
return {
|
||||
key: minifiedName,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@ const INITIAL_VALUE = {
|
|||
};
|
||||
const NOT_SUPPORTED: any = 'NOT_SUPPORTED';
|
||||
|
||||
function getInputPropertyMapName(name: string): string {
|
||||
return `input_${name}`;
|
||||
}
|
||||
|
||||
function getOutputPropertyMapName(name: string): string {
|
||||
return `output_${name}`;
|
||||
}
|
||||
|
||||
export class UpgradeNg1ComponentAdapterBuilder {
|
||||
// TODO(issue/24571): remove '!'.
|
||||
|
|
@ -33,7 +40,7 @@ export class UpgradeNg1ComponentAdapterBuilder {
|
|||
propertyMap: {[name: string]: string} = {};
|
||||
directive: IDirective|null = null;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
template !: string;
|
||||
template!: string;
|
||||
|
||||
constructor(public name: string) {
|
||||
const selector =
|
||||
|
|
@ -76,9 +83,9 @@ export class UpgradeNg1ComponentAdapterBuilder {
|
|||
|
||||
// QUESTION: What about `=*`? Ignore? Throw? Support?
|
||||
|
||||
const inputName = `input_${attrName}`;
|
||||
const inputName = getInputPropertyMapName(attrName);
|
||||
const inputNameRename = `${inputName}: ${attrName}`;
|
||||
const outputName = `output_${attrName}`;
|
||||
const outputName = getOutputPropertyMapName(attrName);
|
||||
const outputNameRename = `${outputName}: ${attrName}`;
|
||||
const outputNameRenameChange = `${outputNameRename}Change`;
|
||||
|
||||
|
|
@ -225,8 +232,9 @@ class UpgradeNg1ComponentAdapter implements OnInit, OnChanges, DoCheck {
|
|||
const ng1Changes: any = {};
|
||||
Object.keys(changes).forEach(name => {
|
||||
const change: SimpleChange = changes[name];
|
||||
this.setComponentProperty(name, change.currentValue);
|
||||
ng1Changes[this.propertyMap[name]] = change;
|
||||
const propertyMapName = getInputPropertyMapName(name);
|
||||
this.setComponentProperty(propertyMapName, change.currentValue);
|
||||
ng1Changes[this.propertyMap[propertyMapName]] = change;
|
||||
});
|
||||
|
||||
if (isFunction(this.destinationObj!.$onChanges)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue