*
* 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:
*
*
* 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
{
[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:
*
*
* 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 {
[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)
* or for each single/multi property that exists in the context.
*/
export const enum StylingFlags {
// Implies no configurations
None = 0b000000,
// Whether or not the entry or context itself is dirty
Dirty = 0b000001,
// Whether or not this is a class-based assignment
Class = 0b000010,
// Whether or not a sanitizer was applied to this property
Sanitize = 0b000100,
// Whether or not any player builders within need to produce new players
PlayerBuildersDirty = 0b001000,
// If NgClass is present (or some other class handler) then it will handle the map expressions and
// initial classes
OnlyProcessSingleClasses = 0b010000,
// The max amount of bits used to represent these configuration values
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 {
// Index of location where the start of single properties are stored. (`updateStyleProp`)
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
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)
CachedClassValueOrInitialClassString = 6,
// Position of where the last string-based CSS class value was stored
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,
PlayerBuilderIndexOffset = 3,
// Size of each multi or single entry (flag + prop + value + playerBuilderIndex)
Size = 4,
// Each flag has a binary digit length of this value
BitCountSize = 14, // (32 - 4) / 2 = ~14
// 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
}