code: function processCompositions( topPage, pageRef ) {
  
        return processNestedCompositions( topPage, pageRef, null, [] );
  
        function processNestedCompositions( page, pageRef, instanceId, compositionChain ) {
  
           page.debugInfo = {
              id: instanceId,
              name: page.name,
              path: page.path,
              //validate: validators.features.pages[ page.name ],
              compositions: [],
              [ FLAT ]: page.definition,
              [ COMPACT ]: deepClone( page.definition )
           };
  
           let promise = Promise.resolve();
  
           forEachArea( page, (items, areaName) => {
              items.slice().reverse().forEach( (item, index) => {
                 if( item.enabled === false ) {
                    return;
                 }
                 ensureItemHasId( item );
                 if( !has( item, 'composition' ) ) {
                    return;
                 }
  
                 const compositionRef = item.composition;
                 if( compositionChain.indexOf( compositionRef ) !== -1 ) {
                    const chainString = compositionChain.concat( [ compositionRef ] ).join( ' -> ' );
                    const message = `Cycle in compositions detected: ${chainString}`;
                    throw formatError( topPage, message );
                 }
  
                 const itemPointer = `/areas/${areaName}/${items.length - index - 1}`;
  
                 // Compositions must be loaded sequentially, because replacing the widgets in the page needs to
                 // take place in order. Otherwise the order of widgets could be messed up.
                 promise = promise
                    .then( () => prefixCompositionIds( lookup( compositionRef ), item ) )
                    .then( composition =>
                       processCompositionExpressions( composition, item, itemPointer, pageRef )
                    )
                    .then( composition => {
                       const chain = compositionChain.concat( composition.name );
                       return processNestedCompositions( composition, compositionRef, item.id, chain );
                    } )
                    .then( composition => {
                       page.debugInfo.compositions.push( composition.debugInfo );
                       mergeCompositionAreasWithPageAreas( composition, page.definition, items, item );
                       validateWidgetItems( composition, compositionRef );
                    } );
              } );
           } );
  
           return promise
              .then( () => page );
        }
     }
docs: /////////////////////////////////////////////////////////////////////////////////////////////////////////  Processing compositions  /////////////////////////////////////////////////////////////////////////////////////////////////////////