refactor(ivy): simplify differentiation of LView, RNode, LView, LContainer, StylingContext (#28947)

For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`,
`StylingContext`) in same location in `LView`. This is because we don't want to pre-allocate
space
for it because the storage is sparse. This file contains utilities for dealing with such data
types.
How do we know what is stored at a given location in `LView`.
- `Array.isArray(value) === false` => `RNode` (The normal storage value)
- `Array.isArray(value) === true` => than the `value[0]` represents the wrapped value.
  - `typeof value[TYPE] === 'object'` => `LView`
     - This happens when we have a component at a given location
  - `typeof value[TYPE] === 'number'` => `StylingContext`
     - This happens when we have style/class binding at a given location.
  - `typeof value[TYPE] === true` => `LContainer`
     - This happens when we have `LContainer` binding at a given location.
NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.

PR Close #28947
This commit is contained in:
Misko Hevery
2019-02-23 11:14:35 -08:00
committed by Miško Hevery
parent bd65f58784
commit 3cb497c6ac
19 changed files with 225 additions and 112 deletions

View File

@ -12,9 +12,9 @@ import {assertDomNode} from '../util/assert';
import {EMPTY_ARRAY} from './empty';
import {LContext, MONKEY_PATCH_KEY_NAME} from './interfaces/context';
import {TNode, TNodeFlags} from './interfaces/node';
import {RElement} from './interfaces/renderer';
import {RElement, RNode} from './interfaces/renderer';
import {CONTEXT, HEADER_OFFSET, HOST, LView, TVIEW} from './interfaces/view';
import {getComponentViewByIndex, getNativeByTNode, readElementValue, readPatchedData} from './util/view_utils';
import {getComponentViewByIndex, getNativeByTNode, readPatchedData, unwrapRNode} from './util/view_utils';
@ -71,7 +71,7 @@ export function getLContext(target: any): LContext|null {
// are expensive. Instead, only the target data (the element, component, container, ICU
// expression or directive details) are filled into the context. If called multiple times
// with different target values then the missing target data will be filled in.
const native = readElementValue(lView[nodeIndex]);
const native = unwrapRNode(lView[nodeIndex]);
const existingCtx = readPatchedData(native);
const context: LContext = (existingCtx && !Array.isArray(existingCtx)) ?
existingCtx :
@ -119,7 +119,7 @@ export function getLContext(target: any): LContext|null {
const index = findViaNativeElement(lView, rElement);
if (index >= 0) {
const native = readElementValue(lView[index]);
const native = unwrapRNode(lView[index]);
const context = createLContext(lView, index, native);
attachPatchData(native, context);
mpValue = context;
@ -134,7 +134,7 @@ export function getLContext(target: any): LContext|null {
/**
* Creates an empty instance of a `LContext` context
*/
function createLContext(lView: LView, nodeIndex: number, native: RElement): LContext {
function createLContext(lView: LView, nodeIndex: number, native: RNode): LContext {
return {
lView,
nodeIndex,