refactor(core): refactor WrappedValue (#20997)

- Improve `WrappedValue` by adding `unwrap` symetrical to `wrap`.
- remove dead code - `ValueUnwrapper`

The property `wrapped` is an implementation details and should never be accessed
directly - use `unwrap(wrappedValue)`. Will change to protected in Angular 7.

PR Close #20997
This commit is contained in:
Victor Berchet 2017-12-13 15:54:43 -08:00 committed by Alex Eagle
parent 54bf179888
commit 3bcc0e6f76
6 changed files with 26 additions and 34 deletions

View File

@ -12,7 +12,7 @@ import {IterableDifferFactory, IterableDiffers} from './differs/iterable_differs
import {KeyValueDifferFactory, KeyValueDiffers} from './differs/keyvalue_differs';
export {SimpleChanges} from '../metadata/lifecycle_hooks';
export {SimpleChange, ValueUnwrapper, WrappedValue, devModeEqual} from './change_detection_util';
export {SimpleChange, WrappedValue, devModeEqual} from './change_detection_util';
export {ChangeDetectorRef} from './change_detector_ref';
export {ChangeDetectionStrategy, ChangeDetectorStatus, isDefaultChangeDetectionStrategy} from './constants';
export {DefaultIterableDifferFactory} from './differs/default_iterable_differ';

View File

@ -26,10 +26,10 @@ export function devModeEqual(a: any, b: any): boolean {
/**
* Indicates that the result of a {@link Pipe} transformation has changed even though the
* reference
* has not changed.
* reference has not changed.
*
* The wrapped value will be unwrapped by change detection, and the unwrapped value will be stored.
* Wrapped values are unwrapped automatically during the change detection, and the unwrapped value
* is stored.
*
* Example:
*
@ -44,26 +44,22 @@ export function devModeEqual(a: any, b: any): boolean {
* @stable
*/
export class WrappedValue {
constructor(public wrapped: any) {}
/** @deprecated from 5.3, use `unwrap()` instead - will switch to protected */
wrapped: any;
constructor(value: any) { this.wrapped = value; }
/** Creates a wrapped value. */
static wrap(value: any): WrappedValue { return new WrappedValue(value); }
}
/**
* Helper class for unwrapping WrappedValue s
*/
export class ValueUnwrapper {
public hasWrappedValue = false;
/**
* Returns the underlying value of a wrapped value.
* Returns the given `value` when it is not wrapped.
**/
static unwrap(value: any): any { return WrappedValue.isWrapped(value) ? value.wrapped : value; }
unwrap(value: any): any {
if (value instanceof WrappedValue) {
this.hasWrappedValue = true;
return value.wrapped;
}
return value;
}
reset() { this.hasWrappedValue = false; }
/** Returns true if `value` is a wrapped value. */
static isWrapped(value: any): value is WrappedValue { return value instanceof WrappedValue; }
}
/**

View File

@ -8,7 +8,7 @@
export {ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS} from './application_ref';
export {APP_ID_RANDOM_PROVIDER as ɵAPP_ID_RANDOM_PROVIDER} from './application_tokens';
export {ValueUnwrapper as ɵValueUnwrapper, devModeEqual as ɵdevModeEqual} from './change_detection/change_detection_util';
export {devModeEqual as ɵdevModeEqual} from './change_detection/change_detection_util';
export {isListLikeIterable as ɵisListLikeIterable} from './change_detection/change_detection_util';
export {ChangeDetectorStatus as ɵChangeDetectorStatus, isDefaultChangeDetectionStrategy as ɵisDefaultChangeDetectionStrategy} from './change_detection/constants';
export {Console as ɵConsole} from './console';

View File

@ -437,10 +437,7 @@ function updateProp(
providerData.instance[propName] = value;
if (def.flags & NodeFlags.OnChanges) {
changes = changes || {};
let oldValue = view.oldValues[def.bindingIndex + bindingIdx];
if (oldValue instanceof WrappedValue) {
oldValue = oldValue.wrapped;
}
const oldValue = WrappedValue.unwrap(view.oldValues[def.bindingIndex + bindingIdx]);
const binding = def.bindings[bindingIdx];
changes[binding.nonMinifiedName !] =
new SimpleChange(oldValue, value, (view.state & ViewState.FirstCheck) !== 0);

View File

@ -28,13 +28,10 @@ export function tokenKey(token: any): string {
}
export function unwrapValue(view: ViewData, nodeIdx: number, bindingIdx: number, value: any): any {
if (value instanceof WrappedValue) {
value = value.wrapped;
let globalBindingIdx = view.def.nodes[nodeIdx].bindingIndex + bindingIdx;
let oldValue = view.oldValues[globalBindingIdx];
if (oldValue instanceof WrappedValue) {
oldValue = oldValue.wrapped;
}
if (WrappedValue.isWrapped(value)) {
value = WrappedValue.unwrap(value);
const globalBindingIdx = view.def.nodes[nodeIdx].bindingIndex + bindingIdx;
const oldValue = WrappedValue.unwrap(view.oldValues[globalBindingIdx]);
view.oldValues[globalBindingIdx] = new WrappedValue(oldValue);
}
return value;

View File

@ -1093,8 +1093,10 @@ export declare abstract class ViewRef extends ChangeDetectorRef {
/** @stable */
export declare class WrappedValue {
wrapped: any;
constructor(wrapped: any);
/** @deprecated */ wrapped: any;
constructor(value: any);
static isWrapped(value: any): value is WrappedValue;
static unwrap(value: any): any;
static wrap(value: any): WrappedValue;
}