feat(core): view engine - add WrappedValue support (#14216)

Part of #14013
This commit is contained in:
Tobias Bosch
2017-01-31 11:08:29 -08:00
committed by Miško Hevery
parent 1bc5368ea0
commit 08ff67ea11
9 changed files with 327 additions and 104 deletions

View File

@ -10,7 +10,7 @@ import {isDevMode} from '../application_ref';
import {SecurityContext} from '../security';
import {BindingDef, BindingType, DebugContext, DisposableFn, ElementData, ElementOutputDef, EntryAction, NodeData, NodeDef, NodeFlags, NodeType, QueryValueType, ViewData, ViewDefinition, ViewFlags, asElementData} from './types';
import {checkAndUpdateBinding, entryAction, setBindingDebugInfo, setCurrentNode, sliceErrorStack} from './util';
import {checkAndUpdateBinding, entryAction, setBindingDebugInfo, setCurrentNode, sliceErrorStack, unwrapValue} from './util';
export function anchorDef(
flags: NodeFlags, matchedQueries: [string, QueryValueType][], ngContentIndex: number,
@ -248,6 +248,7 @@ function checkAndUpdateElementValue(view: ViewData, def: NodeDef, bindingIdx: nu
if (!checkAndUpdateBinding(view, def, bindingIdx, value)) {
return;
}
value = unwrapValue(value);
const binding = def.bindings[bindingIdx];
const name = binding.name;

View File

@ -17,7 +17,7 @@ import {Renderer} from '../render/api';
import {queryDef} from './query';
import {BindingDef, BindingType, DepDef, DepFlags, DisposableFn, EntryAction, NodeData, NodeDef, NodeFlags, NodeType, ProviderData, ProviderOutputDef, QueryBindingType, QueryDef, QueryValueType, Services, ViewData, ViewDefinition, ViewFlags, asElementData, asProviderData} from './types';
import {checkAndUpdateBinding, checkAndUpdateBindingWithChange, entryAction, setBindingDebugInfo, setCurrentNode} from './util';
import {checkAndUpdateBinding, checkAndUpdateBindingWithChange, entryAction, setBindingDebugInfo, setCurrentNode, unwrapValue} from './util';
const _tokenKeyCache = new Map<any, string>();
@ -278,6 +278,7 @@ function checkAndUpdateProp(
changed = checkAndUpdateBinding(view, def, bindingIdx, value);
}
if (changed) {
value = unwrapValue(value);
const binding = def.bindings[bindingIdx];
const propName = binding.name;
// Note: This is still safe with Closure Compiler as

View File

@ -8,7 +8,7 @@
import {resolveDep, tokenKey} from './provider';
import {BindingDef, BindingType, DepDef, DepFlags, NodeData, NodeDef, NodeType, ProviderData, PureExpressionData, PureExpressionType, ViewData, asPureExpressionData} from './types';
import {checkAndUpdateBinding} from './util';
import {checkAndUpdateBinding, unwrapValue} from './util';
export function purePipeDef(pipeToken: any, argCount: number): NodeDef {
return _pureExpressionDef(
@ -99,6 +99,17 @@ export function checkAndUpdatePureExpressionInline(
}
if (changed) {
v0 = unwrapValue(v0);
v1 = unwrapValue(v1);
v2 = unwrapValue(v2);
v3 = unwrapValue(v3);
v4 = unwrapValue(v4);
v5 = unwrapValue(v5);
v6 = unwrapValue(v6);
v7 = unwrapValue(v7);
v8 = unwrapValue(v8);
v9 = unwrapValue(v9);
const data = asPureExpressionData(view, def.index);
let value: any;
switch (def.pureExpression.type) {
@ -121,7 +132,7 @@ export function checkAndUpdatePureExpressionInline(
case 4:
value[3] = v3;
case 3:
value[2] = v2;
value[3] = v2;
case 2:
value[1] = v1;
case 1:
@ -208,16 +219,23 @@ export function checkAndUpdatePureExpressionDynamic(view: ViewData, def: NodeDef
let value: any;
switch (def.pureExpression.type) {
case PureExpressionType.Array:
value = values;
value = new Array(values.length);
for (let i = 0; i < values.length; i++) {
value[i] = unwrapValue(values[i]);
}
break;
case PureExpressionType.Object:
value = {};
for (let i = 0; i < values.length; i++) {
value[bindings[i].name] = values[i];
value[bindings[i].name] = unwrapValue(values[i]);
}
break;
case PureExpressionType.Pipe:
value = data.pipe.transform(values[0], ...values.slice(1));
const params = new Array(values.length);
for (let i = 0; i < values.length; i++) {
params[i] = unwrapValue(values[i]);
}
value = data.pipe.transform(params[0], ...params.slice(1));
break;
}
data.value = value;

View File

@ -10,7 +10,7 @@ import {isDevMode} from '../application_ref';
import {looseIdentical} from '../facade/lang';
import {BindingDef, BindingType, DebugContext, NodeData, NodeDef, NodeFlags, NodeType, Services, TextData, ViewData, ViewFlags, asElementData, asTextData} from './types';
import {checkAndUpdateBinding, sliceErrorStack} from './util';
import {checkAndUpdateBinding, sliceErrorStack, unwrapValue} from './util';
export function textDef(ngContentIndex: number, constants: string[]): NodeDef {
// skip the call to sliceErrorStack itself + the call to this function.
@ -156,6 +156,7 @@ export function checkAndUpdateTextDynamic(view: ViewData, def: NodeDef, values:
}
function _addInterpolationPart(value: any, binding: BindingDef): string {
value = unwrapValue(value);
const valueStr = value != null ? value.toString() : '';
return valueStr + binding.suffix;
}

View File

@ -7,7 +7,7 @@
*/
import {isDevMode} from '../application_ref';
import {devModeEqual} from '../change_detection/change_detection';
import {WrappedValue, devModeEqual} from '../change_detection/change_detection';
import {SimpleChange} from '../change_detection/change_detection_util';
import {looseIdentical} from '../facade/lang';
import {Renderer} from '../render/api';
@ -63,6 +63,13 @@ export function checkAndUpdateBindingWithChange(
return null;
}
export function unwrapValue(value: any): any {
if (value instanceof WrappedValue) {
value = value.wrapped;
}
return value;
}
export function declaredViewContainer(view: ViewData): ElementData {
if (view.parent) {
const parentView = view.parent;