fix(ivy): merge static style rendering across elements, directives and components (#27661)
PR Close #27661
This commit is contained in:
@ -9,130 +9,199 @@ import {StyleSanitizeFn} from '../../sanitization/style_sanitizer';
|
||||
import {RElement} from '../interfaces/renderer';
|
||||
import {PlayerContext} from './player';
|
||||
|
||||
|
||||
/**
|
||||
* The styling context acts as a styling manifest (shaped as an array) for determining which
|
||||
* styling properties have been assigned via the provided `updateStylingMap`, `updateStyleProp`
|
||||
* and `updateClassProp` functions. There are also two initialization functions
|
||||
* `allocStylingContext` and `createStylingContextTemplate` which are used to initialize
|
||||
* and/or clone the context.
|
||||
* and `updateClassProp` functions. It also stores the static style/class values that were
|
||||
* extracted from the template by the compiler.
|
||||
*
|
||||
* The context is an array where the first two cells are used for static data (initial styling)
|
||||
* and dirty flags / index offsets). The remaining set of cells is used for multi (map) and single
|
||||
* (prop) style values.
|
||||
* A context is created by Angular when:
|
||||
* 1. An element contains static styling values (like style="..." or class="...")
|
||||
* 2. An element contains single property binding values (like [style.prop]="x" or
|
||||
* [class.prop]="y")
|
||||
* 3. An element contains multi property binding values (like [style]="x" or [class]="y")
|
||||
* 4. A directive contains host bindings for static, single or multi styling properties/bindings.
|
||||
* 5. An animation player is added to an element via `addPlayer`
|
||||
*
|
||||
* each value from here onwards is mapped as so:
|
||||
* [i] = mutation/type flag for the style/class value
|
||||
* [i + 1] = prop string (or null incase it has been removed)
|
||||
* [i + 2] = value string (or null incase it has been removed)
|
||||
*
|
||||
* There are three types of styling types stored in this context:
|
||||
* initial: any styles that are passed in once the context is created
|
||||
* (these are stored in the first cell of the array and the first
|
||||
* value of this array is always `null` even if no initial styling exists.
|
||||
* the `null` value is there so that any new styles have a parent to point
|
||||
* to. This way we can always assume that there is a parent.)
|
||||
*
|
||||
* single: any styles that are updated using `updateStyleProp` or `updateClassProp` (fixed set)
|
||||
*
|
||||
* multi: any styles that are updated using `updateStylingMap` (dynamic set)
|
||||
*
|
||||
* Note that context is only used to collect style information. Only when `renderStyling`
|
||||
* is called is when the styling payload will be rendered (or built as a key/value map).
|
||||
*
|
||||
* When the context is created, depending on what initial styling values are passed in, the
|
||||
* context itself will be pre-filled with slots based on the initial style properties. Say
|
||||
* for example we have a series of initial styles that look like so:
|
||||
*
|
||||
* style="width:100px; height:200px;"
|
||||
* class="foo"
|
||||
*
|
||||
* Then the initial state of the context (once initialized) will look like so:
|
||||
* Note that even if an element contains static styling then this context will be created and
|
||||
* attached to it. The reason why this happens (instead of treating styles/classes as regular
|
||||
* HTML attributes) is because the style/class bindings must be able to default themselves back
|
||||
* to their respective static values when they are set to null.
|
||||
*
|
||||
* Say for example we have this:
|
||||
* ```
|
||||
* <!-- when myWidthExp=null then a width of "100px"
|
||||
* will be used a default value for width -->
|
||||
* <div style="width:100px" [style.width]="myWidthExp"></div>
|
||||
* ```
|
||||
*
|
||||
* Even in the situation where there are no bindings, the static styling is still placed into the
|
||||
* context because there may be another directive on the same element that has styling.
|
||||
*
|
||||
* When Angular initializes styling data for an element then it will first register the static
|
||||
* styling values on the element using one of these two instructions:
|
||||
*
|
||||
* 1. elementStart or element (within the template function of a component)
|
||||
* 2. elementHostAttrs (for directive host bindings)
|
||||
*
|
||||
* In either case, a styling context will be created and stored within an element's LViewData. Once
|
||||
* the styling context is created then single and multi properties can stored within it. For this to
|
||||
* happen, the following function needs to be called:
|
||||
*
|
||||
* `elementStyling` (called with style properties, class properties and a sanitizer + a directive
|
||||
* instance).
|
||||
*
|
||||
* When this instruction is called it will populate the styling context with the provided style
|
||||
* and class names into the context.
|
||||
*
|
||||
* The context itself looks like this:
|
||||
*
|
||||
* context = [
|
||||
* element,
|
||||
* playerContext | null,
|
||||
* styleSanitizer | null,
|
||||
* [null, '100px', '200px', true], // property names are not needed since they have already been
|
||||
* written to DOM.
|
||||
*
|
||||
* configMasterVal,
|
||||
* 1, // this instructs how many `style` values there are so that class index values can be
|
||||
* offsetted
|
||||
* { classOne: true, classTwo: false } | 'classOne classTwo' | null // last class value provided
|
||||
* into updateStylingMap
|
||||
* { styleOne: '100px', styleTwo: 0 } | null // last style value provided into updateStylingMap
|
||||
*
|
||||
* // 8
|
||||
* 'width',
|
||||
* pointers(1, 15); // Point to static `width`: `100px` and multi `width`.
|
||||
* null,
|
||||
*
|
||||
* // 11
|
||||
* 'height',
|
||||
* pointers(2, 18); // Point to static `height`: `200px` and multi `height`.
|
||||
* null,
|
||||
*
|
||||
* // 14
|
||||
* 'foo',
|
||||
* pointers(1, 21); // Point to static `foo`: `true` and multi `foo`.
|
||||
* null,
|
||||
*
|
||||
* // 17
|
||||
* 'width',
|
||||
* pointers(1, 6); // Point to static `width`: `100px` and single `width`.
|
||||
* null,
|
||||
*
|
||||
* // 21
|
||||
* 'height',
|
||||
* pointers(2, 9); // Point to static `height`: `200px` and single `height`.
|
||||
* null,
|
||||
*
|
||||
* // 24
|
||||
* 'foo',
|
||||
* pointers(3, 12); // Point to static `foo`: `true` and single `foo`.
|
||||
* null,
|
||||
* // 0-8: header values (about 8 entries of configuration data)
|
||||
* // 9+: this is where each entry is stored:
|
||||
* ]
|
||||
*
|
||||
* function pointers(staticIndex: number, dynamicIndex: number) {
|
||||
* // combine the two indices into a single word.
|
||||
* return (staticIndex << StylingFlags.BitCountSize) |
|
||||
* (dynamicIndex << (StylingIndex.BitCountSize + StylingFlags.BitCountSize));
|
||||
* Let's say we have the following template code:
|
||||
*
|
||||
* ```
|
||||
* <div class="foo bar"
|
||||
* style="width:200px; color:red"
|
||||
* [style.width]="myWidthExp"
|
||||
* [style.height]="myHeightExp"
|
||||
* [class.baz]="myBazExp">
|
||||
* ```
|
||||
*
|
||||
* The context generated from these values will look like this (note that
|
||||
* for each binding name (the class and style bindings) the values will
|
||||
* be inserted twice into the array (once for single property entries) and
|
||||
* another for multi property entries).
|
||||
*
|
||||
* context = [
|
||||
* // 0-8: header values (about 8 entries of configuration data)
|
||||
* // 9+: this is where each entry is stored:
|
||||
*
|
||||
* // SINGLE PROPERTIES
|
||||
* configForWidth,
|
||||
* 'width'
|
||||
* myWidthExp, // the binding value not the binding itself
|
||||
* 0, // the directive owner
|
||||
*
|
||||
* configForHeight,
|
||||
* 'height'
|
||||
* myHeightExp, // the binding value not the binding itself
|
||||
* 0, // the directive owner
|
||||
*
|
||||
* configForBazClass,
|
||||
* 'baz
|
||||
* myBazClassExp, // the binding value not the binding itself
|
||||
* 0, // the directive owner
|
||||
*
|
||||
* // MULTI PROPERTIES
|
||||
* configForWidth,
|
||||
* 'width'
|
||||
* myWidthExp, // the binding value not the binding itself
|
||||
* 0, // the directive owner
|
||||
*
|
||||
* configForHeight,
|
||||
* 'height'
|
||||
* myHeightExp, // the binding value not the binding itself
|
||||
* 0, // the directive owner
|
||||
*
|
||||
* configForBazClass,
|
||||
* 'baz
|
||||
* myBazClassExp, // the binding value not the binding itself
|
||||
* 0, // the directive owner
|
||||
* ]
|
||||
*
|
||||
* The configuration values are left out of the example above because
|
||||
* the ordering of them could change between code patches. Please read the
|
||||
* documentation below to get a better understand of what the configuration
|
||||
* values are and how they work.
|
||||
*
|
||||
* Each time a binding property is updated (whether it be through a single
|
||||
* property instruction like `elementStyleProp`, `elementClassProp` or
|
||||
* `elementStylingMap`) then the values in the context will be updated as
|
||||
* well.
|
||||
*
|
||||
* If for example `[style.width]` updates to `555px` then its value will be reflected
|
||||
* in the context as so:
|
||||
*
|
||||
* context = [
|
||||
* // ...
|
||||
* configForWidth, // this will be marked DIRTY
|
||||
* 'width'
|
||||
* '555px',
|
||||
* 0,
|
||||
* //..
|
||||
* ]
|
||||
*
|
||||
* The context and directive data will also be marked dirty.
|
||||
*
|
||||
* Despite the context being updated, nothing has been rendered on screen (not styles or
|
||||
* classes have been set on the element). To kick off rendering for an element the following
|
||||
* function needs to be run `elementStylingApply`.
|
||||
*
|
||||
* `elementStylingApply` will run through the context and find each dirty value and render them onto
|
||||
* the element. Once complete, all styles/classes will be set to clean. Because of this, the render
|
||||
* function will now know not to rerun itself again if called again unless new style/class values
|
||||
* have changed.
|
||||
*
|
||||
* ## Directives
|
||||
* Directives style values (which are provided through host bindings) are also supported and
|
||||
* housed within the same styling context as are template-level style/class properties/bindings.
|
||||
* Both directive-level and template-level styling bindings share the same context.
|
||||
*
|
||||
* Each of the following instructions supports accepting a directive instance as an input parameter:
|
||||
*
|
||||
* - `elementHostAttrs`
|
||||
* - `elementStyling`
|
||||
* - `elementStyleProp`
|
||||
* - `elementClassProp`
|
||||
* - `elementStylingMap`
|
||||
* - `elementStylingApply`
|
||||
*
|
||||
* Each time a directiveRef is passed in, it will be converted into an index by examining the
|
||||
* directive registry (which lives in the context configuration area). The index is then used
|
||||
* to help single style properties figure out where a value is located in the context.
|
||||
*
|
||||
* If two directives or a directive + a template binding both write to the same style/class
|
||||
* binding then the styling context code will decide which one wins based on the following
|
||||
* rule:
|
||||
*
|
||||
* 1. If the template binding has a value then it always wins
|
||||
* 2. If not then whichever first-registered directive that has that value first will win
|
||||
*
|
||||
* The code example helps make this clear:
|
||||
*
|
||||
* ```
|
||||
* <div [style.width]="myWidth" [my-width-directive]="'600px">
|
||||
* @Directive({ selector: '[my-width-directive' ]})
|
||||
* class MyWidthDirective {
|
||||
* @Input('my-width-directive')
|
||||
* @HostBinding('style.width')
|
||||
* public width = null;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The values are duplicated so that space is set aside for both multi ([style] and [class])
|
||||
* and single ([style.prop] or [class.named]) values. The respective config values
|
||||
* (configValA, configValB, etc...) are a combination of the StylingFlags with two index
|
||||
* values: the `initialIndex` (which points to the index location of the style value in
|
||||
* the initial styles array in slot 0) and the `dynamicIndex` (which points to the
|
||||
* matching single/multi index position in the context array for the same prop).
|
||||
* Since there is a style binding for width present on the element (`[style.width]`) then
|
||||
* it will always win over the width binding that is present as a host binding within
|
||||
* the `MyWidthDirective`. However, if `[style.width]` renders as `null` (so `myWidth=null`)
|
||||
* then the `MyWidthDirective` will be able to write to the `width` style within the context.
|
||||
* Simply put, whichever directive writes to a value ends up having ownership of it.
|
||||
*
|
||||
* This means that every time `updateStyleProp` or `updateClassProp` are called then they
|
||||
* must be called using an index value (not a property string) which references the index
|
||||
* value of the initial style prop/class when the context was created. This also means that
|
||||
* `updateStyleProp` or `updateClassProp` cannot be called with a new property (only
|
||||
* `updateStylingMap` can include new CSS properties that will be added to the context).
|
||||
* The way in which the ownership is facilitated is through index value. The earliest directives
|
||||
* get the smallest index values (with 0 being reserved for the template element bindings). Each
|
||||
* time a value is written from a directive or the template bindings, the value itself gets
|
||||
* assigned the directive index value in its data. If another directive writes a value again then
|
||||
* its directive index gets compared against the directive index that exists on the element. Only
|
||||
* when the new value's directive index is less than the existing directive index then the new
|
||||
* value will be written to the context.
|
||||
*
|
||||
* Each directive also has its own sanitizer and dirty flags. These values are consumed within the
|
||||
* rendering function.
|
||||
*/
|
||||
export interface StylingContext extends Array<InitialStyles|{[key: string]: any}|number|string|
|
||||
boolean|RElement|StyleSanitizeFn|PlayerContext|null> {
|
||||
/**
|
||||
* Location of animation context (which contains the active players) for this element styling
|
||||
* context.
|
||||
*/
|
||||
[StylingIndex.PlayerContext]: PlayerContext|null;
|
||||
|
||||
/**
|
||||
* The style sanitizer that is used within this context
|
||||
*/
|
||||
[StylingIndex.StyleSanitizerPosition]: StyleSanitizeFn|null;
|
||||
|
||||
/**
|
||||
* Location of initial data shared by all instances of this style.
|
||||
*/
|
||||
[StylingIndex.InitialStylesPosition]: InitialStyles;
|
||||
|
||||
export interface StylingContext extends
|
||||
Array<{[key: string]: any}|number|string|boolean|RElement|StyleSanitizeFn|PlayerContext|null> {
|
||||
/**
|
||||
* A numeric value representing the configuration status (whether the context is dirty or not)
|
||||
* mixed together (using bit shifting) with a index value which tells the starting index value
|
||||
@ -140,12 +209,27 @@ export interface StylingContext extends Array<InitialStyles|{[key: string]: any}
|
||||
*/
|
||||
[StylingIndex.MasterFlagPosition]: number;
|
||||
|
||||
/**
|
||||
* Location of the collection of directives for this context
|
||||
*/
|
||||
[StylingIndex.DirectiveRegistryPosition]: DirectiveRegistryValues;
|
||||
|
||||
/**
|
||||
* Location of all static styles values
|
||||
*/
|
||||
[StylingIndex.InitialStyleValuesPosition]: InitialStylingValues;
|
||||
|
||||
/**
|
||||
* Location of all static class values
|
||||
*/
|
||||
[StylingIndex.InitialClassValuesPosition]: InitialStylingValues;
|
||||
|
||||
/**
|
||||
* A numeric value representing the class index offset value. Whenever a single class is
|
||||
* applied (using `elementClassProp`) it should have an styling index value that doesn't
|
||||
* need to take into account any style values that exist in the context.
|
||||
*/
|
||||
[StylingIndex.ClassOffsetPosition]: number;
|
||||
[StylingIndex.SinglePropOffsetPositions]: SinglePropOffsetValues;
|
||||
|
||||
/**
|
||||
* Location of element that is used as a target for this context.
|
||||
@ -156,24 +240,206 @@ export interface StylingContext extends Array<InitialStyles|{[key: string]: any}
|
||||
* The last class value that was interpreted by elementStylingMap. This is cached
|
||||
* So that the algorithm can exit early incase the value has not changed.
|
||||
*/
|
||||
[StylingIndex.PreviousOrCachedMultiClassValue]: {[key: string]: any}|string|null;
|
||||
[StylingIndex.CachedClassValueOrInitialClassString]: {[key: string]: any}|string|(string)[]|null;
|
||||
|
||||
/**
|
||||
* The last style value that was interpreted by elementStylingMap. This is cached
|
||||
* So that the algorithm can exit early incase the value has not changed.
|
||||
*/
|
||||
[StylingIndex.PreviousMultiStyleValue]: {[key: string]: any}|null;
|
||||
[StylingIndex.CachedStyleValue]: {[key: string]: any}|(string)[]|null;
|
||||
|
||||
/**
|
||||
* Location of animation context (which contains the active players) for this element styling
|
||||
* context.
|
||||
*/
|
||||
[StylingIndex.PlayerContext]: PlayerContext|null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The initial styles is populated whether or not there are any initial styles passed into
|
||||
* the context during allocation. The 0th value must be null so that index values of `0` within
|
||||
* the context flags can always point to a null value safely when nothing is set.
|
||||
* Used as a styling array to house static class and style values that were extracted
|
||||
* by the compiler and placed in the animation context via `elementStart` and
|
||||
* `elementHostAttrs`.
|
||||
*
|
||||
* All other entries in this array are of `string` value and correspond to the values that
|
||||
* were extracted from the `style=""` attribute in the HTML code for the provided template.
|
||||
* See [InitialStylingValuesIndex] for a breakdown of how all this works.
|
||||
*/
|
||||
export interface InitialStyles extends Array<string|null|boolean> { [0]: null; }
|
||||
export interface InitialStylingValues extends Array<string|boolean|null> { [0]: null; }
|
||||
|
||||
/**
|
||||
* Used as an offset/position index to figure out where initial styling
|
||||
* values are located.
|
||||
*
|
||||
* Used as a reference point to provide markers to all static styling
|
||||
* values (the initial style and class values on an element) within an
|
||||
* array within the StylingContext. This array contains key/value pairs
|
||||
* where the key is the style property name or className and the value is
|
||||
* the style value or whether or not a class is present on the elment.
|
||||
*
|
||||
* The first value is also always null so that a initial index value of
|
||||
* `0` will always point to a null value.
|
||||
*
|
||||
* If a <div> elements contains a list of static styling values like so:
|
||||
*
|
||||
* <div class="foo bar baz" style="width:100px; height:200px;">
|
||||
*
|
||||
* Then the initial styles for that will look like so:
|
||||
*
|
||||
* Styles:
|
||||
* StylingContext[InitialStylesIndex] = [
|
||||
* null, 'width', '100px', height, '200px'
|
||||
* ]
|
||||
*
|
||||
* Classes:
|
||||
* StylingContext[InitialStylesIndex] = [
|
||||
* null, 'foo', true, 'bar', true, 'baz', true
|
||||
* ]
|
||||
*
|
||||
* Initial style and class entries have their own arrays. This is because
|
||||
* it's easier to add to the end of one array and not then have to update
|
||||
* every context entries' pointer index to the newly offseted values.
|
||||
*
|
||||
* When property bindinds are added to a context then initial style/class
|
||||
* values will also be inserted into the array. This is to create a space
|
||||
* in the situation when a follow-up directive inserts static styling into
|
||||
* the array. By default style values are `null` and class values are
|
||||
* `false` when inserted by property bindings.
|
||||
*
|
||||
* For example:
|
||||
* <div class="foo bar baz"
|
||||
* [class.car]="myCarExp"
|
||||
* style="width:100px; height:200px;"
|
||||
* [style.opacity]="myOpacityExp">
|
||||
*
|
||||
* Will construct initial styling values that look like:
|
||||
*
|
||||
* Styles:
|
||||
* StylingContext[InitialStylesIndex] = [
|
||||
* null, 'width', '100px', height, '200px', 'opacity', null
|
||||
* ]
|
||||
*
|
||||
* Classes:
|
||||
* StylingContext[InitialStylesIndex] = [
|
||||
* null, 'foo', true, 'bar', true, 'baz', true, 'car', false
|
||||
* ]
|
||||
*
|
||||
* Now if a directive comes along and introduces `car` as a static
|
||||
* class value or `opacity` then those values will be filled into
|
||||
* the initial styles array.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
* @Directive({
|
||||
* selector: 'opacity-car-directive',
|
||||
* host: {
|
||||
* 'style': 'opacity:0.5',
|
||||
* 'class': 'car'
|
||||
* }
|
||||
* })
|
||||
* class OpacityCarDirective {}
|
||||
*
|
||||
* This will render itself as:
|
||||
*
|
||||
* Styles:
|
||||
* StylingContext[InitialStylesIndex] = [
|
||||
* null, 'width', '100px', height, '200px', 'opacity', null
|
||||
* ]
|
||||
*
|
||||
* Classes:
|
||||
* StylingContext[InitialStylesIndex] = [
|
||||
* null, 'foo', true, 'bar', true, 'baz', true, 'car', false
|
||||
* ]
|
||||
*/
|
||||
export const enum InitialStylingValuesIndex {
|
||||
KeyValueStartPosition = 1,
|
||||
PropOffset = 0,
|
||||
ValueOffset = 1,
|
||||
Size = 2
|
||||
}
|
||||
|
||||
/**
|
||||
* An array located in the StylingContext that houses all directive instances and additional
|
||||
* data about them.
|
||||
*
|
||||
* Each entry in this array represents a source of where style/class binding values could
|
||||
* come from. By default, there is always at least one directive here with a null value and
|
||||
* that represents bindings that live directly on an element (not host bindings).
|
||||
*
|
||||
* Each successive entry in the array is an actual instance of an array as well as some
|
||||
* additional info.
|
||||
*
|
||||
* An entry within this array has the following values:
|
||||
* [0] = The instance of the directive (or null when it is not a directive, but a template binding
|
||||
* source)
|
||||
* [1] = The pointer that tells where the single styling (stuff like [class.foo] and [style.prop])
|
||||
* offset values are located. This value will allow for a binding instruction to find exactly
|
||||
* where a style is located.
|
||||
* [2] = Whether or not the directive has any styling values that are dirty. This is used as
|
||||
* reference within the renderClassAndStyleBindings function to decide whether to skip
|
||||
* iterating through the context when rendering is executed.
|
||||
* [3] = The styleSanitizer instance that is assigned to the directive. Although it's unlikely,
|
||||
* a directive could introduce its own special style sanitizer and for this reach each
|
||||
* directive will get its own space for it (if null then the very first sanitizer is used).
|
||||
*
|
||||
* Each time a new directive is added it will insert these four values at the end of the array.
|
||||
* When this array is examined (using indexOf) then the resulting directiveIndex will be resolved
|
||||
* by dividing the index value by the size of the array entries (so if DirA is at spot 8 then its
|
||||
* index will be 2).
|
||||
*/
|
||||
export interface DirectiveRegistryValues extends Array<null|{}|boolean|number|StyleSanitizeFn> {
|
||||
[DirectiveRegistryValuesIndex.DirectiveValueOffset]: null;
|
||||
[DirectiveRegistryValuesIndex.SinglePropValuesIndexOffset]: number;
|
||||
[DirectiveRegistryValuesIndex.DirtyFlagOffset]: boolean;
|
||||
[DirectiveRegistryValuesIndex.StyleSanitizerOffset]: StyleSanitizeFn|null;
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum that outlines the offset/position values for each directive entry and its data
|
||||
* that are housed inside of [DirectiveRegistryValues].
|
||||
*/
|
||||
export const enum DirectiveRegistryValuesIndex {
|
||||
DirectiveValueOffset = 0,
|
||||
SinglePropValuesIndexOffset = 1,
|
||||
DirtyFlagOffset = 2,
|
||||
StyleSanitizerOffset = 3,
|
||||
Size = 4
|
||||
}
|
||||
|
||||
/**
|
||||
* An array that contains the index pointer values for every single styling property
|
||||
* that exists in the context and for every directive. It also contains the total
|
||||
* single styles and single classes that exists in the context as the first two values.
|
||||
*
|
||||
* Let's say we have the following template code:
|
||||
*
|
||||
* <div [style.width]="myWidth"
|
||||
* [style.height]="myHeight"
|
||||
* [class.flipped]="flipClass"
|
||||
* directive-with-opacity>
|
||||
* directive-with-foo-bar-classes>
|
||||
*
|
||||
* We have two directive and template-binding sources,
|
||||
* 2 + 1 styles and 1 + 1 classes. When the bindings are
|
||||
* registered the SinglePropOffsets array will look like so:
|
||||
*
|
||||
* s_0/c_0 = template directive value
|
||||
* s_1/c_1 = directive one (directive-with-opacity)
|
||||
* s_2/c_2 = directive two (directive-with-foo-bar-classes)
|
||||
*
|
||||
* [3, 2, 2, 1, s_00, s01, c_01, 1, 0, s_10, 0, 1, c_20
|
||||
*/
|
||||
export interface SinglePropOffsetValues extends Array<number> {
|
||||
[SinglePropOffsetValuesIndex.StylesCountPosition]: number;
|
||||
[SinglePropOffsetValuesIndex.ClassesCountPosition]: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum that outlines the offset/position values for each single prop/class entry
|
||||
* that are housed inside of [SinglePropOffsetValues].
|
||||
*/
|
||||
export const enum SinglePropOffsetValuesIndex {
|
||||
StylesCountPosition = 0,
|
||||
ClassesCountPosition = 1,
|
||||
ValueStartPosition = 2
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to set the context to be dirty or not both on the master flag (position 1)
|
||||
@ -181,47 +447,49 @@ export interface InitialStyles extends Array<string|null|boolean> { [0]: null; }
|
||||
*/
|
||||
export const enum StylingFlags {
|
||||
// Implies no configurations
|
||||
None = 0b00000,
|
||||
None = 0b000000,
|
||||
// Whether or not the entry or context itself is dirty
|
||||
Dirty = 0b00001,
|
||||
Dirty = 0b000001,
|
||||
// Whether or not this is a class-based assignment
|
||||
Class = 0b00010,
|
||||
Class = 0b000010,
|
||||
// Whether or not a sanitizer was applied to this property
|
||||
Sanitize = 0b00100,
|
||||
Sanitize = 0b000100,
|
||||
// Whether or not any player builders within need to produce new players
|
||||
PlayerBuildersDirty = 0b01000,
|
||||
PlayerBuildersDirty = 0b001000,
|
||||
// If NgClass is present (or some other class handler) then it will handle the map expressions and
|
||||
// initial classes
|
||||
OnlyProcessSingleClasses = 0b10000,
|
||||
OnlyProcessSingleClasses = 0b010000,
|
||||
// The max amount of bits used to represent these configuration values
|
||||
BitCountSize = 5,
|
||||
// There are only five bits here
|
||||
BitMask = 0b11111
|
||||
BindingAllocationLocked = 0b100000,
|
||||
BitCountSize = 6,
|
||||
// There are only six bits here
|
||||
BitMask = 0b111111
|
||||
}
|
||||
|
||||
/** Used as numeric pointer values to determine what cells to update in the `StylingContext` */
|
||||
export const enum StylingIndex {
|
||||
// Position of where the initial styles are stored in the styling context
|
||||
PlayerContext = 0,
|
||||
// Position of where the style sanitizer is stored within the styling context
|
||||
StyleSanitizerPosition = 1,
|
||||
// Position of where the initial styles are stored in the styling context
|
||||
InitialStylesPosition = 2,
|
||||
// Index of location where the start of single properties are stored. (`updateStyleProp`)
|
||||
MasterFlagPosition = 3,
|
||||
MasterFlagPosition = 0,
|
||||
// Position of where the registered directives exist for this styling context
|
||||
DirectiveRegistryPosition = 1,
|
||||
// Position of where the initial styles are stored in the styling context
|
||||
InitialStyleValuesPosition = 2,
|
||||
InitialClassValuesPosition = 3,
|
||||
// Index of location where the class index offset value is located
|
||||
ClassOffsetPosition = 4,
|
||||
SinglePropOffsetPositions = 4,
|
||||
// Position of where the initial styles are stored in the styling context
|
||||
// This index must align with HOST, see interfaces/view.ts
|
||||
ElementPosition = 5,
|
||||
// Position of where the last string-based CSS class value was stored (or a cached version of the
|
||||
// initial styles when a [class] directive is present)
|
||||
PreviousOrCachedMultiClassValue = 6,
|
||||
CachedClassValueOrInitialClassString = 6,
|
||||
// Position of where the last string-based CSS class value was stored
|
||||
PreviousMultiStyleValue = 7,
|
||||
// Location of single (prop) value entries are stored within the context
|
||||
SingleStylesStartPosition = 8,
|
||||
CachedStyleValue = 7,
|
||||
// Multi and single entries are stored in `StylingContext` as: Flag; PropertyName; PropertyValue
|
||||
// Position of where the initial styles are stored in the styling context
|
||||
PlayerContext = 8,
|
||||
// Location of single (prop) value entries are stored within the context
|
||||
SingleStylesStartPosition = 9,
|
||||
FlagsOffset = 0,
|
||||
PropertyOffset = 1,
|
||||
ValueOffset = 2,
|
||||
@ -233,3 +501,16 @@ export const enum StylingIndex {
|
||||
// The binary digit value as a mask
|
||||
BitMask = 0b11111111111111, // 14 bits
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum that outlines the bit flag data for directive owner and player index
|
||||
* values that exist within en entry that lives in the StylingContext.
|
||||
*
|
||||
* The values here split a number value into two sets of bits:
|
||||
* - The first 16 bits are used to store the directiveIndex that owns this style value
|
||||
* - The other 16 bits are used to store the playerBuilderIndex that is attached to this style
|
||||
*/
|
||||
export const enum DirectiveOwnerAndPlayerBuilderIndex {
|
||||
BitCountSize = 16,
|
||||
BitMask = 0b1111111111111111
|
||||
}
|
||||
|
Reference in New Issue
Block a user