From 28ce68a13d93f06acbcbc127128248b89568dc8d Mon Sep 17 00:00:00 2001 From: Tobias Bosch Date: Fri, 17 Mar 2017 09:23:28 -0700 Subject: [PATCH] refactor(core): view engine - change `BindingType` to `BindingFlags` (#15251) --- modules/benchmarks/src/tree/ng2_next/tree.ts | 4 +- .../src/view_compiler/view_compiler.ts | 20 +++---- packages/core/src/codegen_private_exports.ts | 2 +- packages/core/src/view/element.ts | 56 +++++++++---------- packages/core/src/view/ng_content.ts | 1 + packages/core/src/view/provider.ts | 9 +-- packages/core/src/view/pure_expression.ts | 7 ++- packages/core/src/view/query.ts | 1 + packages/core/src/view/refs.ts | 2 +- packages/core/src/view/services.ts | 9 ++- packages/core/src/view/text.ts | 7 ++- packages/core/src/view/types.ts | 21 +++---- packages/core/src/view/util.ts | 10 +++- .../core/test/view/component_view_spec.ts | 6 +- packages/core/test/view/element_spec.ts | 19 ++++--- packages/core/test/view/embedded_view_spec.ts | 4 +- packages/core/test/view/provider_spec.ts | 2 +- packages/core/test/view/query_spec.ts | 2 +- 18 files changed, 95 insertions(+), 87 deletions(-) diff --git a/modules/benchmarks/src/tree/ng2_next/tree.ts b/modules/benchmarks/src/tree/ng2_next/tree.ts index f85d86face..95bdc911bf 100644 --- a/modules/benchmarks/src/tree/ng2_next/tree.ts +++ b/modules/benchmarks/src/tree/ng2_next/tree.ts @@ -8,7 +8,7 @@ import {NgIf} from '@angular/common'; import {ComponentFactory, ComponentFactoryResolver, ComponentRef, Injector, NgModuleRef, RendererFactory2, RootRenderer, Sanitizer, TemplateRef, ViewContainerRef} from '@angular/core'; -import {ArgumentType, BindingType, NodeFlags, ViewDefinition, ViewFlags, anchorDef, createComponentFactory, directiveDef, elementDef, initServicesIfNeeded, textDef, viewDef} from '@angular/core/src/view/index'; +import {ArgumentType, BindingFlags, NodeFlags, ViewDefinition, ViewFlags, anchorDef, createComponentFactory, directiveDef, elementDef, initServicesIfNeeded, textDef, viewDef} from '@angular/core/src/view/index'; import {DomRendererFactory2} from '@angular/platform-browser/src/dom/dom_renderer'; import {DomSanitizerImpl, SafeStyle} from '@angular/platform-browser/src/security/dom_sanitization_service'; @@ -63,7 +63,7 @@ function TreeComponent_0(): ViewDefinition { [ elementDef( NodeFlags.None, null, null, 1, 'span', null, - [[BindingType.ElementStyle, 'backgroundColor', null]]), + [[BindingFlags.TypeElementStyle, 'backgroundColor', null]]), textDef(null, [' ', ' ']), anchorDef(NodeFlags.EmbeddedViews, null, null, 1, null, TreeComponent_1), directiveDef( diff --git a/packages/compiler/src/view_compiler/view_compiler.ts b/packages/compiler/src/view_compiler/view_compiler.ts index 1a8dd29807..0f2c31781e 100644 --- a/packages/compiler/src/view_compiler/view_compiler.ts +++ b/packages/compiler/src/view_compiler/view_compiler.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {ChangeDetectionStrategy, ViewEncapsulation, ɵArgumentType as ArgumentType, ɵBindingType as BindingType, ɵDepFlags as DepFlags, ɵLifecycleHooks as LifecycleHooks, ɵNodeFlags as NodeFlags, ɵQueryBindingType as QueryBindingType, ɵQueryValueType as QueryValueType, ɵViewFlags as ViewFlags, ɵelementEventFullName as elementEventFullName} from '@angular/core'; +import {ChangeDetectionStrategy, ViewEncapsulation, ɵArgumentType as ArgumentType, ɵBindingFlags as BindingFlags, ɵDepFlags as DepFlags, ɵLifecycleHooks as LifecycleHooks, ɵNodeFlags as NodeFlags, ɵQueryBindingType as QueryBindingType, ɵQueryValueType as QueryValueType, ɵViewFlags as ViewFlags, ɵelementEventFullName as elementEventFullName} from '@angular/core'; import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileDirectiveSummary, CompilePipeSummary, CompileProviderMetadata, CompileTokenMetadata, CompileTypeMetadata, identifierModuleUrl, identifierName, rendererTypeName, tokenReference, viewClassName} from '../compile_metadata'; import {BuiltinConverter, BuiltinConverterFactory, EventHandlerVars, LocalResolver, convertActionBinding, convertPropertyBinding, convertPropertyBindingBuiltins} from '../compiler_util/expression_converter'; @@ -355,10 +355,7 @@ class ViewBuilder implements TemplateAstVisitor, LocalResolver { // flags: NodeFlags, matchedQueriesDsl: [string | number, QueryValueType][], // ngContentIndex: number, childCount: number, namespaceAndName: string, // fixedAttrs: [string, string][] = [], - // bindings?: - // ([BindingType.ElementClass, string] | [BindingType.ElementStyle, string, string] | - // [BindingType.ElementAttribute | BindingType.ElementProperty | - // BindingType.DirectiveHostProperty, string, SecurityContext])[], + // bindings?: [BindingFlags, string, string | SecurityContext][], // outputs?: ([OutputType.ElementOutput | OutputType.DirectiveHostOutput, string, string])[], // handleEvent?: ElementHandleEventFn, // componentView?: () => ViewDefinition, componentRendererType?: RendererType2): NodeDef; @@ -1024,26 +1021,27 @@ function elementBindingDef(inputAst: BoundElementPropertyAst, dirAst: DirectiveA switch (inputAst.type) { case PropertyBindingType.Attribute: return o.literalArr([ - o.literal(BindingType.ElementAttribute), o.literal(inputAst.name), + o.literal(BindingFlags.TypeElementAttribute), o.literal(inputAst.name), o.literal(inputAst.securityContext) ]); case PropertyBindingType.Property: return o.literalArr([ - o.literal(BindingType.ElementProperty), o.literal(inputAst.name), + o.literal(BindingFlags.TypeProperty), o.literal(inputAst.name), o.literal(inputAst.securityContext) ]); case PropertyBindingType.Animation: const bindingType = dirAst && dirAst.directive.isComponent ? - BindingType.ComponentHostProperty : - BindingType.ElementProperty; + BindingFlags.TypeProperty | BindingFlags.SyntheticComponentHostProperty : + BindingFlags.TypeProperty; return o.literalArr([ o.literal(bindingType), o.literal('@' + inputAst.name), o.literal(inputAst.securityContext) ]); case PropertyBindingType.Class: - return o.literalArr([o.literal(BindingType.ElementClass), o.literal(inputAst.name)]); + return o.literalArr( + [o.literal(BindingFlags.TypeElementClass), o.literal(inputAst.name), o.NULL_EXPR]); case PropertyBindingType.Style: return o.literalArr([ - o.literal(BindingType.ElementStyle), o.literal(inputAst.name), o.literal(inputAst.unit) + o.literal(BindingFlags.TypeElementStyle), o.literal(inputAst.name), o.literal(inputAst.unit) ]); } } diff --git a/packages/core/src/codegen_private_exports.ts b/packages/core/src/codegen_private_exports.ts index c82bdbb0c0..fadaed4122 100644 --- a/packages/core/src/codegen_private_exports.ts +++ b/packages/core/src/codegen_private_exports.ts @@ -10,4 +10,4 @@ export {CodegenComponentFactoryResolver as ɵCodegenComponentFactoryResolver} fr export {NgModuleInjector as ɵNgModuleInjector} from './linker/ng_module_factory'; export {registerModuleFactory as ɵregisterModuleFactory} from './linker/ng_module_factory_loader'; export {reflector as ɵreflector} from './reflection/reflection'; -export {ArgumentType as ɵArgumentType, BindingType as ɵBindingType, DepFlags as ɵDepFlags, EMPTY_ARRAY as ɵEMPTY_ARRAY, EMPTY_MAP as ɵEMPTY_MAP, NodeFlags as ɵNodeFlags, QueryBindingType as ɵQueryBindingType, QueryValueType as ɵQueryValueType, ViewDefinition as ɵViewDefinition, ViewFlags as ɵViewFlags, anchorDef as ɵand, createComponentFactory as ɵccf, createRendererType2 as ɵcrt, directiveDef as ɵdid, elementDef as ɵeld, elementEventFullName as ɵelementEventFullName, getComponentViewDefinitionFactory as ɵgetComponentViewDefinitionFactory, inlineInterpolate as ɵinlineInterpolate, interpolate as ɵinterpolate, ngContentDef as ɵncd, nodeValue as ɵnov, pipeDef as ɵpid, providerDef as ɵprd, pureArrayDef as ɵpad, pureObjectDef as ɵpod, purePipeDef as ɵppd, queryDef as ɵqud, textDef as ɵted, unwrapValue as ɵunv, viewDef as ɵvid} from './view/index'; +export {ArgumentType as ɵArgumentType, BindingFlags as ɵBindingFlags, DepFlags as ɵDepFlags, EMPTY_ARRAY as ɵEMPTY_ARRAY, EMPTY_MAP as ɵEMPTY_MAP, NodeFlags as ɵNodeFlags, QueryBindingType as ɵQueryBindingType, QueryValueType as ɵQueryValueType, ViewDefinition as ɵViewDefinition, ViewFlags as ɵViewFlags, anchorDef as ɵand, createComponentFactory as ɵccf, createRendererType2 as ɵcrt, directiveDef as ɵdid, elementDef as ɵeld, elementEventFullName as ɵelementEventFullName, getComponentViewDefinitionFactory as ɵgetComponentViewDefinitionFactory, inlineInterpolate as ɵinlineInterpolate, interpolate as ɵinterpolate, ngContentDef as ɵncd, nodeValue as ɵnov, pipeDef as ɵpid, providerDef as ɵprd, pureArrayDef as ɵpad, pureObjectDef as ɵpod, purePipeDef as ɵppd, queryDef as ɵqud, textDef as ɵted, unwrapValue as ɵunv, viewDef as ɵvid} from './view/index'; diff --git a/packages/core/src/view/element.ts b/packages/core/src/view/element.ts index 633e740bff..3bba958a8a 100644 --- a/packages/core/src/view/element.ts +++ b/packages/core/src/view/element.ts @@ -10,8 +10,8 @@ import {ViewEncapsulation} from '../metadata/view'; import {Renderer2, RendererType2} from '../render/api'; import {SecurityContext} from '../security'; -import {BindingDef, BindingType, DebugContext, DisposableFn, ElementData, ElementHandleEventFn, NodeData, NodeDef, NodeFlags, OutputDef, OutputType, QueryValueType, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, asElementData, asProviderData} from './types'; -import {NOOP, checkAndUpdateBinding, dispatchEvent, elementEventFullName, filterQueryId, getParentRenderElement, resolveRendererType2, resolveViewDefinition, splitMatchedQueriesDsl, splitNamespace} from './util'; +import {BindingDef, BindingFlags, DebugContext, DisposableFn, ElementData, ElementHandleEventFn, NodeData, NodeDef, NodeFlags, OutputDef, OutputType, QueryValueType, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, asElementData, asProviderData} from './types'; +import {NOOP, calcBindingFlags, checkAndUpdateBinding, dispatchEvent, elementEventFullName, filterQueryId, getParentRenderElement, resolveRendererType2, resolveViewDefinition, splitMatchedQueriesDsl, splitNamespace} from './util'; export function anchorDef( flags: NodeFlags, matchedQueriesDsl: [string | number, QueryValueType][], @@ -37,6 +37,7 @@ export function anchorDef( directChildFlags: 0, childMatchedQueries: 0, matchedQueries, matchedQueryIds, references, ngContentIndex, childCount, bindings: [], + bindingFlags: 0, outputs: [], element: { ns: undefined, @@ -59,15 +60,9 @@ export function elementDef( flags: NodeFlags, matchedQueriesDsl: [string | number, QueryValueType][], ngContentIndex: number, childCount: number, namespaceAndName: string, fixedAttrs: [string, string][] = [], - bindings?: - ([BindingType.ElementClass, string] | [BindingType.ElementStyle, string, string] | - [ - BindingType.ElementAttribute | BindingType.ElementProperty | - BindingType.ComponentHostProperty, - string, SecurityContext - ])[], - outputs?: ([string, string])[], handleEvent?: ElementHandleEventFn, - componentView?: ViewDefinitionFactory, componentRendererType?: RendererType2): NodeDef { + bindings?: [BindingFlags, string, string | SecurityContext][], outputs?: ([string, string])[], + handleEvent?: ElementHandleEventFn, componentView?: ViewDefinitionFactory, + componentRendererType?: RendererType2): NodeDef { if (!handleEvent) { handleEvent = NOOP; } @@ -80,23 +75,22 @@ export function elementDef( bindings = bindings || []; const bindingDefs: BindingDef[] = new Array(bindings.length); for (let i = 0; i < bindings.length; i++) { - const entry = bindings[i]; + const [bindingFlags, namespaceAndName, suffixOrSecurityContext] = bindings[i]; let bindingDef: BindingDef; - const bindingType = entry[0]; - const [ns, name] = splitNamespace(entry[1]); + const [ns, name] = splitNamespace(namespaceAndName); let securityContext: SecurityContext; let suffix: string; - switch (bindingType) { - case BindingType.ElementStyle: - suffix = entry[2]; + switch (bindingFlags & BindingFlags.Types) { + case BindingFlags.TypeElementStyle: + suffix = suffixOrSecurityContext; break; - case BindingType.ElementAttribute: - case BindingType.ElementProperty: - case BindingType.ComponentHostProperty: - securityContext = entry[2]; + case BindingFlags.TypeElementAttribute: + case BindingFlags.TypeProperty: + securityContext = suffixOrSecurityContext; break; } - bindingDefs[i] = {type: bindingType, ns, name, nonMinifiedName: name, securityContext, suffix}; + bindingDefs[i] = + {flags: bindingFlags, ns, name, nonMinifiedName: name, securityContext, suffix}; } outputs = outputs || []; const outputDefs: OutputDef[] = new Array(outputs.length); @@ -131,6 +125,7 @@ export function elementDef( directChildFlags: 0, childMatchedQueries: 0, matchedQueries, matchedQueryIds, references, ngContentIndex, childCount, bindings: bindingDefs, + bindingFlags: calcBindingFlags(bindingDefs), outputs: outputDefs, element: { ns, @@ -232,21 +227,20 @@ function checkAndUpdateElementValue(view: ViewData, def: NodeDef, bindingIdx: nu const elData = asElementData(view, def.index); const renderNode = elData.renderElement; const name = binding.name; - switch (binding.type) { - case BindingType.ElementAttribute: + switch (binding.flags & BindingFlags.Types) { + case BindingFlags.TypeElementAttribute: setElementAttribute(view, binding, renderNode, binding.ns, name, value); break; - case BindingType.ElementClass: + case BindingFlags.TypeElementClass: setElementClass(view, renderNode, name, value); break; - case BindingType.ElementStyle: + case BindingFlags.TypeElementStyle: setElementStyle(view, binding, renderNode, name, value); break; - case BindingType.ElementProperty: - setElementProperty(view, binding, renderNode, name, value); - break; - case BindingType.ComponentHostProperty: - setElementProperty(elData.componentView, binding, renderNode, name, value); + case BindingFlags.TypeProperty: + const bindView = + binding.flags & BindingFlags.SyntheticComponentHostProperty ? elData.componentView : view; + setElementProperty(bindView, binding, renderNode, name, value); break; } return true; diff --git a/packages/core/src/view/ng_content.ts b/packages/core/src/view/ng_content.ts index d22c4cb800..c7e0c0226c 100644 --- a/packages/core/src/view/ng_content.ts +++ b/packages/core/src/view/ng_content.ts @@ -27,6 +27,7 @@ export function ngContentDef(ngContentIndex: number, index: number): NodeDef { references: {}, ngContentIndex, childCount: 0, bindings: [], + bindingFlags: 0, outputs: [], element: undefined, provider: undefined, diff --git a/packages/core/src/view/provider.ts b/packages/core/src/view/provider.ts index 2c0d8adfd6..a4f0c4619b 100644 --- a/packages/core/src/view/provider.ts +++ b/packages/core/src/view/provider.ts @@ -15,8 +15,8 @@ import {ViewEncapsulation} from '../metadata/view'; import {Renderer as RendererV1, Renderer2, RendererFactory2, RendererType2} from '../render/api'; import {createChangeDetectorRef, createInjector, createRendererV1} from './refs'; -import {BindingDef, BindingType, DepDef, DepFlags, DisposableFn, NodeData, NodeDef, NodeFlags, OutputDef, OutputType, ProviderData, QueryBindingType, QueryDef, QueryValueType, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewState, asElementData, asProviderData} from './types'; -import {checkBinding, dispatchEvent, filterQueryId, isComponentView, splitMatchedQueriesDsl, tokenKey, viewParentEl} from './util'; +import {BindingDef, BindingFlags, DepDef, DepFlags, DisposableFn, NodeData, NodeDef, NodeFlags, OutputDef, OutputType, ProviderData, QueryBindingType, QueryDef, QueryValueType, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewState, asElementData, asProviderData} from './types'; +import {calcBindingFlags, checkBinding, dispatchEvent, filterQueryId, isComponentView, splitMatchedQueriesDsl, tokenKey, viewParentEl} from './util'; const RendererV1TokenKey = tokenKey(RendererV1); const Renderer2TokenKey = tokenKey(Renderer2); @@ -37,7 +37,7 @@ export function directiveDef( for (let prop in props) { const [bindingIndex, nonMinifiedName] = props[prop]; bindings[bindingIndex] = { - type: BindingType.DirectiveProperty, + flags: BindingFlags.TypeProperty, name: prop, nonMinifiedName, ns: undefined, securityContext: undefined, @@ -103,7 +103,8 @@ export function _def( childFlags: 0, directChildFlags: 0, childMatchedQueries: 0, matchedQueries, matchedQueryIds, references, - ngContentIndex: undefined, childCount, bindings, outputs, + ngContentIndex: undefined, childCount, bindings, + bindingFlags: calcBindingFlags(bindings), outputs, element: undefined, provider: {token, tokenKey: tokenKey(token), value, deps: depDefs}, text: undefined, diff --git a/packages/core/src/view/pure_expression.ts b/packages/core/src/view/pure_expression.ts index c35e1e6272..a3e153cba3 100644 --- a/packages/core/src/view/pure_expression.ts +++ b/packages/core/src/view/pure_expression.ts @@ -6,8 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {BindingDef, BindingType, DepDef, DepFlags, NodeData, NodeDef, NodeFlags, ProviderData, PureExpressionData, Services, ViewData, asPureExpressionData} from './types'; -import {checkAndUpdateBinding, tokenKey} from './util'; +import {BindingDef, BindingFlags, DepDef, DepFlags, NodeData, NodeDef, NodeFlags, ProviderData, PureExpressionData, Services, ViewData, asPureExpressionData} from './types'; +import {calcBindingFlags, checkAndUpdateBinding, tokenKey} from './util'; export function purePipeDef(argCount: number): NodeDef { // argCount + 1 to include the pipe as first arg @@ -27,7 +27,7 @@ function _pureExpressionDef(flags: NodeFlags, propertyNames: string[]): NodeDef for (let i = 0; i < propertyNames.length; i++) { const prop = propertyNames[i]; bindings[i] = { - type: BindingType.PureExpressionProperty, + flags: BindingFlags.TypeProperty, name: prop, ns: undefined, nonMinifiedName: prop, @@ -52,6 +52,7 @@ function _pureExpressionDef(flags: NodeFlags, propertyNames: string[]): NodeDef references: {}, ngContentIndex: undefined, childCount: 0, bindings, + bindingFlags: calcBindingFlags(bindings), outputs: [], element: undefined, provider: undefined, diff --git a/packages/core/src/view/query.ts b/packages/core/src/view/query.ts index f38bb1c7fc..63deb0c7b9 100644 --- a/packages/core/src/view/query.ts +++ b/packages/core/src/view/query.ts @@ -40,6 +40,7 @@ export function queryDef( references: {}, childCount: 0, bindings: [], + bindingFlags: 0, outputs: [], element: undefined, provider: undefined, diff --git a/packages/core/src/view/refs.ts b/packages/core/src/view/refs.ts index 70413c3d08..eb39e946a7 100644 --- a/packages/core/src/view/refs.ts +++ b/packages/core/src/view/refs.ts @@ -19,7 +19,7 @@ import {Renderer as RendererV1, Renderer2} from '../render/api'; import {Type} from '../type'; import {VERSION} from '../version'; -import {ArgumentType, BindingType, DebugContext, DepFlags, ElementData, NodeCheckFn, NodeData, NodeDef, NodeFlags, RootData, Services, TemplateData, ViewContainerData, ViewData, ViewDefinition, ViewDefinitionFactory, ViewState, asElementData, asProviderData, asTextData} from './types'; +import {ArgumentType, BindingFlags, DebugContext, DepFlags, ElementData, NodeCheckFn, NodeData, NodeDef, NodeFlags, RootData, Services, TemplateData, ViewContainerData, ViewData, ViewDefinition, ViewDefinitionFactory, ViewState, asElementData, asProviderData, asTextData} from './types'; import {isComponentView, markParentViewsForCheck, renderNode, resolveViewDefinition, rootRenderNodes, splitNamespace, tokenKey, viewParentEl} from './util'; import {attachEmbeddedView, detachEmbeddedView, moveEmbeddedView, renderDetachView} from './view_attach'; diff --git a/packages/core/src/view/services.ts b/packages/core/src/view/services.ts index caa07cd426..39945d5eec 100644 --- a/packages/core/src/view/services.ts +++ b/packages/core/src/view/services.ts @@ -17,7 +17,7 @@ import {isViewDebugError, viewDestroyedError, viewWrappedDebugError} from './err import {resolveDep} from './provider'; import {dirtyParentQueries, getQueryValue} from './query'; import {createInjector} from './refs'; -import {ArgumentType, BindingType, CheckType, DebugContext, DepFlags, ElementData, NodeCheckFn, NodeData, NodeDef, NodeFlags, NodeLogger, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewState, asElementData, asProviderData, asPureExpressionData} from './types'; +import {ArgumentType, BindingFlags, CheckType, DebugContext, DepFlags, ElementData, NodeCheckFn, NodeData, NodeDef, NodeFlags, NodeLogger, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewState, asElementData, asProviderData, asPureExpressionData} from './types'; import {NOOP, checkBinding, isComponentView, renderNode, viewParentEl} from './util'; import {checkAndUpdateNode, checkAndUpdateView, checkNoChangesNode, checkNoChangesView, createEmbeddedView, createRootView, destroyView} from './view'; @@ -225,18 +225,17 @@ function debugCheckAndUpdateNode( const changed = (checkAndUpdateNode)(view, nodeDef, argStyle, ...givenValues); if (changed) { const values = argStyle === ArgumentType.Dynamic ? givenValues[0] : givenValues; - if (nodeDef.flags & (NodeFlags.TypeDirective | NodeFlags.TypeElement)) { + if (nodeDef.flags & NodeFlags.TypeDirective) { const bindingValues: {[key: string]: string} = {}; for (let i = 0; i < nodeDef.bindings.length; i++) { const binding = nodeDef.bindings[i]; const value = values[i]; - if ((binding.type === BindingType.ComponentHostProperty || - binding.type === BindingType.DirectiveProperty)) { + if (binding.flags & BindingFlags.TypeProperty) { bindingValues[normalizeDebugBindingName(binding.nonMinifiedName)] = normalizeDebugBindingValue(value); } } - const elDef = nodeDef.flags & NodeFlags.TypeDirective ? nodeDef.parent : nodeDef; + const elDef = nodeDef.parent; const el = asElementData(view, elDef.index).renderElement; if (!elDef.element.name) { // a comment. diff --git a/packages/core/src/view/text.ts b/packages/core/src/view/text.ts index a96358b1c1..e5b2e22764 100644 --- a/packages/core/src/view/text.ts +++ b/packages/core/src/view/text.ts @@ -8,14 +8,14 @@ import {looseIdentical} from '../util'; -import {BindingDef, BindingType, DebugContext, NodeData, NodeDef, NodeFlags, RootData, Services, TextData, ViewData, ViewFlags, asElementData, asTextData} from './types'; -import {checkAndUpdateBinding, getParentRenderElement} from './util'; +import {BindingDef, BindingFlags, DebugContext, NodeData, NodeDef, NodeFlags, RootData, Services, TextData, ViewData, ViewFlags, asElementData, asTextData} from './types'; +import {calcBindingFlags, checkAndUpdateBinding, getParentRenderElement} from './util'; export function textDef(ngContentIndex: number, constants: string[]): NodeDef { const bindings: BindingDef[] = new Array(constants.length - 1); for (let i = 1; i < constants.length; i++) { bindings[i - 1] = { - type: BindingType.TextInterpolation, + flags: BindingFlags.TypeProperty, name: undefined, ns: undefined, nonMinifiedName: undefined, @@ -40,6 +40,7 @@ export function textDef(ngContentIndex: number, constants: string[]): NodeDef { matchedQueryIds: 0, references: {}, ngContentIndex, childCount: 0, bindings, + bindingFlags: calcBindingFlags(bindings), outputs: [], element: undefined, provider: undefined, diff --git a/packages/core/src/view/types.ts b/packages/core/src/view/types.ts index 2426ca3288..f74c732e85 100644 --- a/packages/core/src/view/types.ts +++ b/packages/core/src/view/types.ts @@ -108,6 +108,7 @@ export interface NodeDef { bindingIndex: number; bindings: BindingDef[]; + bindingFlags: BindingFlags; outputIndex: number; outputs: OutputDef[]; /** @@ -181,7 +182,7 @@ export const enum NodeFlags { } export interface BindingDef { - type: BindingType; + flags: BindingFlags; ns: string; name: string; nonMinifiedName: string; @@ -189,15 +190,15 @@ export interface BindingDef { suffix: string; } -export const enum BindingType { - ElementAttribute, - ElementClass, - ElementStyle, - ElementProperty, - ComponentHostProperty, - DirectiveProperty, - TextInterpolation, - PureExpressionProperty +export const enum BindingFlags { + TypeElementAttribute = 1 << 0, + TypeElementClass = 1 << 1, + TypeElementStyle = 1 << 2, + TypeProperty = 1 << 3, + SyntheticComponentHostProperty = 1 << 4, + + // mutually exclusive values... + Types = TypeElementAttribute | TypeElementClass | TypeElementStyle | TypeProperty } export interface OutputDef { diff --git a/packages/core/src/view/util.ts b/packages/core/src/view/util.ts index 18f846eaa8..27ca1feb82 100644 --- a/packages/core/src/view/util.ts +++ b/packages/core/src/view/util.ts @@ -17,7 +17,7 @@ import {Renderer, RendererType2} from '../render/api'; import {looseIdentical, stringify} from '../util'; import {expressionChangedAfterItHasBeenCheckedError, isViewDebugError, viewDestroyedError, viewWrappedDebugError} from './errors'; -import {DebugContext, ElementData, NodeData, NodeDef, NodeFlags, NodeLogger, QueryValueType, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewState, asElementData, asProviderData, asTextData} from './types'; +import {BindingDef, BindingFlags, DebugContext, ElementData, NodeData, NodeDef, NodeFlags, NodeLogger, QueryValueType, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewState, asElementData, asProviderData, asTextData} from './types'; export const NOOP: any = () => {}; @@ -343,6 +343,14 @@ export function splitNamespace(name: string): string[] { return ['', name]; } +export function calcBindingFlags(bindings: BindingDef[]): BindingFlags { + let flags = 0; + for (let i = 0; i < bindings.length; i++) { + flags |= bindings[i].flags; + } + return flags; +} + export function interpolate(valueCount: number, constAndInterp: string[]): string { let result = ''; for (let i = 0; i < valueCount * 2; i = i + 2) { diff --git a/packages/core/test/view/component_view_spec.ts b/packages/core/test/view/component_view_spec.ts index 9e1e2f30a4..dd6b25005a 100644 --- a/packages/core/test/view/component_view_spec.ts +++ b/packages/core/test/view/component_view_spec.ts @@ -7,7 +7,7 @@ */ import {Injector, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation} from '@angular/core'; -import {ArgumentType, BindingType, NodeCheckFn, NodeDef, NodeFlags, OutputType, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewState, ViewUpdateFn, anchorDef, asElementData, asProviderData, directiveDef, elementDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index'; +import {ArgumentType, BindingFlags, NodeCheckFn, NodeDef, NodeFlags, OutputType, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewState, ViewUpdateFn, anchorDef, asElementData, asProviderData, directiveDef, elementDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {createRootView, isBrowser, removeNodes} from './helper'; @@ -120,7 +120,7 @@ export function main() { compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'div', null, null, null, null, () => compViewDef( [ - elementDef(NodeFlags.None, null, null, 0, 'span', null, [[BindingType.ElementAttribute, 'a', SecurityContext.NONE]]), + elementDef(NodeFlags.None, null, null, 0, 'span', null, [[BindingFlags.TypeElementAttribute, 'a', SecurityContext.NONE]]), ], null, update )), directiveDef(NodeFlags.Component, null, 0, AComp, []), @@ -247,7 +247,7 @@ export function main() { const {view, rootNodes} = createAndGetRootNodes(compViewDef([ elementDef(NodeFlags.None, null, null, 1, 'div', null, null, null, null, () => compViewDef( [ - elementDef(NodeFlags.None, null, null, 0, 'span', null, [[BindingType.ElementAttribute, 'a', SecurityContext.NONE]]), + elementDef(NodeFlags.None, null, null, 0, 'span', null, [[BindingFlags.TypeElementAttribute, 'a', SecurityContext.NONE]]), ], null, update)), directiveDef( diff --git a/packages/core/test/view/element_spec.ts b/packages/core/test/view/element_spec.ts index fff4fe0e8d..b59509f183 100644 --- a/packages/core/test/view/element_spec.ts +++ b/packages/core/test/view/element_spec.ts @@ -8,7 +8,7 @@ import {Injector, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation, WrappedValue, getDebugNode} from '@angular/core'; import {getDebugContext} from '@angular/core/src/errors'; -import {ArgumentType, BindingType, DebugContext, NodeDef, NodeFlags, OutputType, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, elementDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index'; +import {ArgumentType, BindingFlags, DebugContext, NodeDef, NodeFlags, OutputType, RootData, Services, ViewData, ViewDefinition, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, elementDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; import {ARG_TYPE_VALUES, checkNodeInlineOrDynamic, createRootView, isBrowser, removeNodes} from './helper'; @@ -80,8 +80,8 @@ export function main() { elementDef( NodeFlags.None, null, null, 0, 'input', null, [ - [BindingType.ElementProperty, 'title', SecurityContext.NONE], - [BindingType.ElementProperty, 'value', SecurityContext.NONE] + [BindingFlags.TypeProperty, 'title', SecurityContext.NONE], + [BindingFlags.TypeProperty, 'value', SecurityContext.NONE] ]), ], null, (check, view) => { @@ -105,8 +105,8 @@ export function main() { elementDef( NodeFlags.None, null, null, 0, 'div', null, [ - [BindingType.ElementAttribute, 'a1', SecurityContext.NONE], - [BindingType.ElementAttribute, 'a2', SecurityContext.NONE] + [BindingFlags.TypeElementAttribute, 'a1', SecurityContext.NONE], + [BindingFlags.TypeElementAttribute, 'a2', SecurityContext.NONE] ]), ], null, (check, view) => { @@ -129,7 +129,10 @@ export function main() { [ elementDef( NodeFlags.None, null, null, 0, 'div', null, - [[BindingType.ElementClass, 'c1'], [BindingType.ElementClass, 'c2']]), + [ + [BindingFlags.TypeElementClass, 'c1', null], + [BindingFlags.TypeElementClass, 'c2', null] + ]), ], (check, view) => { checkNodeInlineOrDynamic(check, view, 0, inlineDynamic, [true, true]); @@ -152,8 +155,8 @@ export function main() { elementDef( NodeFlags.None, null, null, 0, 'div', null, [ - [BindingType.ElementStyle, 'width', 'px'], - [BindingType.ElementStyle, 'color', null] + [BindingFlags.TypeElementStyle, 'width', 'px'], + [BindingFlags.TypeElementStyle, 'color', null] ]), ], null, (check, view) => { diff --git a/packages/core/test/view/embedded_view_spec.ts b/packages/core/test/view/embedded_view_spec.ts index 9e0203582e..480109a44a 100644 --- a/packages/core/test/view/embedded_view_spec.ts +++ b/packages/core/test/view/embedded_view_spec.ts @@ -7,7 +7,7 @@ */ import {Injector, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, ViewEncapsulation} from '@angular/core'; -import {ArgumentType, BindingType, NodeCheckFn, NodeDef, NodeFlags, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, attachEmbeddedView, detachEmbeddedView, directiveDef, elementDef, moveEmbeddedView, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index'; +import {ArgumentType, BindingFlags, NodeCheckFn, NodeDef, NodeFlags, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, attachEmbeddedView, detachEmbeddedView, directiveDef, elementDef, moveEmbeddedView, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index'; import {inject} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; @@ -140,7 +140,7 @@ export function main() { embeddedViewDef( [elementDef( NodeFlags.None, null, null, 0, 'span', null, - [[BindingType.ElementAttribute, 'name', SecurityContext.NONE]])], + [[BindingFlags.TypeElementAttribute, 'name', SecurityContext.NONE]])], update)) ])); diff --git a/packages/core/test/view/provider_spec.ts b/packages/core/test/view/provider_spec.ts index 182a3c2b35..4e826e2d1a 100644 --- a/packages/core/test/view/provider_spec.ts +++ b/packages/core/test/view/provider_spec.ts @@ -8,7 +8,7 @@ import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectorRef, DoCheck, ElementRef, EventEmitter, Injector, OnChanges, OnDestroy, OnInit, RenderComponentType, Renderer, Renderer2, RootRenderer, Sanitizer, SecurityContext, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation, WrappedValue, getDebugNode} from '@angular/core'; import {getDebugContext} from '@angular/core/src/errors'; -import {ArgumentType, BindingType, DebugContext, DepFlags, NodeDef, NodeFlags, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, directiveDef, elementDef, providerDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index'; +import {ArgumentType, BindingFlags, DebugContext, DepFlags, NodeDef, NodeFlags, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, directiveDef, elementDef, providerDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index'; import {TestBed, inject, withModule} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter'; diff --git a/packages/core/test/view/query_spec.ts b/packages/core/test/view/query_spec.ts index 1901b9fd97..5600c5cef8 100644 --- a/packages/core/test/view/query_spec.ts +++ b/packages/core/test/view/query_spec.ts @@ -8,7 +8,7 @@ import {ElementRef, Injector, QueryList, RenderComponentType, RootRenderer, Sanitizer, SecurityContext, TemplateRef, ViewContainerRef, ViewEncapsulation, getDebugNode} from '@angular/core'; import {getDebugContext} from '@angular/core/src/errors'; -import {BindingType, DebugContext, NodeDef, NodeFlags, QueryBindingType, QueryValueType, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, attachEmbeddedView, detachEmbeddedView, directiveDef, elementDef, queryDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index'; +import {BindingFlags, DebugContext, NodeDef, NodeFlags, QueryBindingType, QueryValueType, RootData, Services, ViewData, ViewDefinition, ViewDefinitionFactory, ViewFlags, ViewHandleEventFn, ViewUpdateFn, anchorDef, asElementData, asProviderData, attachEmbeddedView, detachEmbeddedView, directiveDef, elementDef, queryDef, rootRenderNodes, textDef, viewDef} from '@angular/core/src/view/index'; import {inject} from '@angular/core/testing'; import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';