feat(ivy): implement host bindings in JIT mode (#24479)
PR Close #24479
This commit is contained in:

committed by
Miško Hevery

parent
6d246d6c72
commit
f00ae516eb
@ -6,9 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ConstantPool, R3DirectiveMetadata, WrappedNodeExpr, compileComponentFromMetadata as compileR3Component, compileDirectiveFromMetadata as compileR3Directive, jitExpression, makeBindingParser, parseTemplate} from '@angular/compiler';
|
||||
import {ConstantPool, R3DirectiveMetadata, WrappedNodeExpr, compileComponentFromMetadata as compileR3Component, compileDirectiveFromMetadata as compileR3Directive, jitExpression, makeBindingParser, parseHostBindings, parseTemplate} from '@angular/compiler';
|
||||
|
||||
import {Component, Directive, HostBinding, Input, Output} from '../../metadata/directives';
|
||||
import {Component, Directive, HostBinding, HostListener, Input, Output} from '../../metadata/directives';
|
||||
import {ReflectionCapabilities} from '../../reflection/reflection_capabilities';
|
||||
import {Type} from '../../type';
|
||||
|
||||
@ -19,6 +19,10 @@ import {getReflect, reflectDependencies} from './util';
|
||||
|
||||
let _pendingPromises: Promise<void>[] = [];
|
||||
|
||||
type StringMap = {
|
||||
[key: string]: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Compile an Angular component according to its decorator metadata, and patch the resulting
|
||||
* ngComponentDef onto the component type.
|
||||
@ -137,12 +141,14 @@ export function awaitCurrentlyCompilingComponents(): Promise<void> {
|
||||
*/
|
||||
function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMetadata {
|
||||
// Reflect inputs and outputs.
|
||||
const props = getReflect().propMetadata(type);
|
||||
const inputs: {[key: string]: string} = {};
|
||||
const outputs: {[key: string]: string} = {};
|
||||
const propMetadata = getReflect().propMetadata(type);
|
||||
const inputs: StringMap = {};
|
||||
const outputs: StringMap = {};
|
||||
|
||||
for (let field in props) {
|
||||
props[field].forEach(ann => {
|
||||
const host = extractHostBindings(metadata, propMetadata);
|
||||
|
||||
for (let field in propMetadata) {
|
||||
propMetadata[field].forEach(ann => {
|
||||
if (isInput(ann)) {
|
||||
inputs[field] = ann.bindingPropertyName || field;
|
||||
} else if (isOutput(ann)) {
|
||||
@ -155,14 +161,7 @@ function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMet
|
||||
name: type.name,
|
||||
type: new WrappedNodeExpr(type),
|
||||
selector: metadata.selector !,
|
||||
deps: reflectDependencies(type),
|
||||
host: {
|
||||
attributes: {},
|
||||
listeners: {},
|
||||
properties: {},
|
||||
},
|
||||
inputs,
|
||||
outputs,
|
||||
deps: reflectDependencies(type), host, inputs, outputs,
|
||||
queries: [],
|
||||
lifecycle: {
|
||||
usesOnChanges: type.prototype.ngOnChanges !== undefined,
|
||||
@ -171,6 +170,32 @@ function directiveMetadata(type: Type<any>, metadata: Directive): R3DirectiveMet
|
||||
};
|
||||
}
|
||||
|
||||
function extractHostBindings(metadata: Directive, propMetadata: {[key: string]: any[]}): {
|
||||
attributes: StringMap,
|
||||
listeners: StringMap,
|
||||
properties: StringMap,
|
||||
} {
|
||||
// First parse the declarations from the metadata.
|
||||
const {attributes, listeners, properties, animations} = parseHostBindings(metadata.host || {});
|
||||
|
||||
if (Object.keys(animations).length > 0) {
|
||||
throw new Error(`Animation bindings are as-of-yet unsupported in Ivy`);
|
||||
}
|
||||
|
||||
// Next, loop over the properties of the object, looking for @HostBinding and @HostListener.
|
||||
for (let field in propMetadata) {
|
||||
propMetadata[field].forEach(ann => {
|
||||
if (isHostBinding(ann)) {
|
||||
properties[ann.hostPropertyName || field] = field;
|
||||
} else if (isHostListener(ann)) {
|
||||
listeners[ann.eventName || field] = `${field}(${(ann.args || []).join(',')})`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {attributes, listeners, properties};
|
||||
}
|
||||
|
||||
function isInput(value: any): value is Input {
|
||||
return value.ngMetadataName === 'Input';
|
||||
}
|
||||
@ -178,3 +203,11 @@ function isInput(value: any): value is Input {
|
||||
function isOutput(value: any): value is Output {
|
||||
return value.ngMetadataName === 'Output';
|
||||
}
|
||||
|
||||
function isHostBinding(value: any): value is HostBinding {
|
||||
return value.ngMetadataName === 'HostBinding';
|
||||
}
|
||||
|
||||
function isHostListener(value: any): value is HostListener {
|
||||
return value.ngMetadataName === 'HostListener';
|
||||
}
|
||||
|
Reference in New Issue
Block a user