import { ArrayProperty , BaseProperty , PropertyFactory , ValueProperty } from "@fluid-experimental/property-properties" ; import { PropertyProxy } from "./propertyProxy" ; import { forceType , Utilities } from "./utilities" ; /**
 * Creates an iterator that can iterate over an  external .
 *  param target The ComponentArray that holds a reference to the
 *  external .
 *  return { Iterator } hidden const createArrayIterator = ( target ) => function * ( ) { for ( let i = 0 ; i < target . getProperty ( ) . getLength ( ) ; i ++ ) { if ( PropertyFactory . instanceOf ( target . getProperty ( ) . get ( i ) ! , "BaseProperty" ) ) { yield PropertyProxy . proxify ( target . getProperty ( ) . get ( i ) ! ) ; } else { yield target . getProperty ( ) . get ( i ) ; } } } ; /**
 * Prepares the elements that are to be inserted into the  external .
 *  param property param elements return hidden const prepareElementsForInsertion = ( property , elements ) => elements . map ( ( element ) => Utilities . prepareElementForInsertion ( property , element ) ) ; /**
 * ComponentArray extends Array to work directly on the data stored in PropertyDDS.
 *  No local copy of the data is maintained.
 * Serves as input for the  ComponentArrayProxyHandler .
 *  extends Array hidden class ComponentArray extends Array { public lastCalledMethod = "" ; /**
     * Sets the  external to operate on sets the Symbol.iterator attribute.
     *  param property constructor ( private readonly property ) { super ( ) ; this . property = property ; this [ Symbol . iterator ] = createArrayIterator ( this ) ; } return getProperty ( ) { return this . property ; } inheritdoc includes ( searchElement , fromIndex ) { let startSearchIdx = 0 ; if ( fromIndex ) { if ( fromIndex >= this . property . getLength ( ) ) { return false ; } else if ( fromIndex < 0 ) { startSearchIdx = Math . max ( 0 , this . property . getLength ( ) + fromIndex ) ; } else { startSearchIdx = Math . min ( fromIndex , this . property . getLength ( ) - 1 ) ; } } if ( searchElement . getProperty ) { searchElement = searchElement . getProperty ( ) ; } for ( let i = startSearchIdx ; i < this . property . length ; ++ i ) { let prop = this . property . get ( i ) ! ; if ( PropertyFactory . instanceOf ( prop , "BaseProperty" ) && prop . isPrimitiveType ( ) && forceType < ValueProperty > ( prop ) ) { prop = prop . getValue ( ) ; } if ( prop === searchElement ) { return true ; } } return false ; } inheritdoc indexOf ( searchElement , fromIndex ? ) { let startSearchIdx = 0 ; if ( fromIndex ) { if ( fromIndex >= this . property . getLength ( ) ) { return - 1 ; } else if ( fromIndex < 0 ) { startSearchIdx = Math . max ( 0 , this . property . getLength ( ) + fromIndex ) ; } else { startSearchIdx = Math . min ( fromIndex , this . property . getLength ( ) - 1 ) ; } } if ( searchElement . getProperty ) { searchElement = searchElement . getProperty ( ) ; } for ( let i = startSearchIdx ; i < this . property . length ; ++ i ) { let prop = this . property . get ( i ) ! ; if ( PropertyFactory . instanceOf ( prop , "BaseProperty" ) && prop . isPrimitiveType ( ) && forceType < ValueProperty > ( prop ) ) { prop = prop . getValue ( ) ; } if ( prop === searchElement ) { return i ; } } return - 1 ; } inheritdoc lastIndexOf ( searchElement , fromIndex ? ) { if ( searchElement . getProperty ) { searchElement = searchElement . getProperty ( ) ; } const startSearchIdx = fromIndex ? ( fromIndex < 0 ? this . property . getLength ( ) + fromIndex : Math . min ( fromIndex , this . property . getLength ( ) - 1 ) ) : this . property . getLength ( ) - 1 ; for ( let i = startSearchIdx ; i >= 0 ; i -- ) { let prop = this . property . get ( i ) ! ; if ( PropertyFactory . instanceOf ( prop , "BaseProperty" ) && prop . isPrimitiveType ( ) && forceType < ValueProperty > ( prop ) ) { prop = prop . getValue ( ) ; } if ( prop === searchElement ) { return i ; } } return - 1 ; } inheritdoc pop ( ) { let popped ; if ( PropertyFactory . instanceOf ( this . property , "Reference" , "array" ) ) { popped = this . property . get ( this . property . getLength ( ) - 1 ) ; this . property . pop ( ) ; } else { popped = this . property . pop ( ) ; } if ( PropertyFactory . instanceOf ( popped , "BaseProperty" ) ) { return PropertyProxy . proxify ( popped ) ; } else { return popped ; } } inheritdoc push ( ... elements ) { const elementsToAdd = elements || [ ] ; if ( elementsToAdd . length === 0 ) { return this . property . getLength ( ) ; } Utilities . wrapWithPushPopNotificationDelayScope ( this . property , ( ) => { elementsToAdd . forEach ( ( el ) => { this . property . push ( Utilities . prepareElementForInsertion ( this . property , el ) ) ; } ) ; } ) ; return this . property . getLength ( ) ; } inheritdoc shift ( ) { let first ; if ( PropertyFactory . instanceOf ( this . property , "Reference" , "array" ) ) { first = this . property . get ( 0 ) ; this . property . shift ( ) ; } else { first = this . property . shift ( ) ; } if ( PropertyFactory . instanceOf ( first , "BaseProperty" ) ) { return PropertyProxy . proxify ( first ) ; } else { return first ; } } inheritdoc sort ( compareFunction ) { this . lastCalledMethod = "sort" ; if ( PropertyFactory . instanceOf ( this . property , "Reference" , "array" ) ) { const referencedAndReference = [ ] ; for ( let i = 0 ; i < this . property . getLength ( ) ; ++ i ) { const referenced = this . property . get ( i ) ! ; if ( PropertyFactory . instanceOf ( referenced , "BaseProperty" ) ) { referencedAndReference . push ( [ PropertyProxy . proxify ( referenced ) , this . property . getValue ( i ) ] ) ; } else { referencedAndReference . push ( [ referenced , this . property . getValue ( i ) ] ) ; } } referencedAndReference . sort ( ( a , b ) => { return compareFunction ( a [ 0 ] , b [ 0 ] ) ; } ) ; this . property . setValues ( referencedAndReference . map ( ( el ) => el [ 1 ] ) ) ; } else { super . sort ( compareFunction ) ; } this . lastCalledMethod = "" ; return this ; } inheritdoc splice ( start , deleteCount , ... items ) { let startValue = Number ( start ) === start ? parseInt ( start , 10 ) : 0 ; const arrayLength = this . property . getLength ( ) ; if ( startValue > arrayLength ) { startValue = arrayLength ; } else if ( startValue < 0 ) { startValue = arrayLength + startValue ; if ( startValue < 0 ) { startValue = 0 ; } } const deleteUntil = Number ( deleteCount ) === deleteCount && startValue + deleteCount < arrayLength ? deleteCount : arrayLength - startValue ; const removed = [ ] ; if ( deleteUntil > 0 && startValue < arrayLength ) { for ( let i = startValue ; i < startValue + deleteUntil ; ++ i ) { removed . push ( this . property . get ( i ) ! ) ; const lastEntryIdx = removed . length - 1 ; if ( PropertyFactory . instanceOf ( removed [ lastEntryIdx ] , "BaseProperty" ) ) { removed [ lastEntryIdx ] = PropertyProxy . proxify ( removed [ lastEntryIdx ] ) ; } } this . property . removeRange ( startValue , deleteUntil ) ; } const itemsToAdd = items || [ ] ; if ( itemsToAdd . length > 0 ) { const preparedElements = prepareElementsForInsertion ( this . property , itemsToAdd ) ; Utilities . wrapWithPushPopNotificationDelayScope ( this . property , ( ) => this . property . insertRange ( startValue , preparedElements ) ) ; } return removed ; } param idxOne param idxTwo swap ( idxOne , idxTwo ) { if ( idxOne >= this . property . getLength ( ) || idxTwo >= this . property . getLength ( ) ) { throw new RangeError ( "Cannot swap element that is out of range" ) ; } const tmp = this [ idxOne ] ; this [ idxOne ] = this [ idxTwo ] ; this [ idxTwo ] = tmp ; } inheritdoc unshift ( ... elements ) { const elementsToAdd = elements || [ ] ; if ( elementsToAdd . length === 0 ) { return this . property . getLength ( ) ; } const preparedElements = prepareElementsForInsertion ( this . property , elementsToAdd ) ; Utilities . wrapWithPushPopNotificationDelayScope ( this . property , ( ) => this . property . insertRange ( 0 , preparedElements ) ) ; return this . property . getLength ( ) ; } } export { ComponentArray } ;