@openui5/sap.ui.core 1.101.0 → 1.102.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (362) hide show
  1. package/.eslintrc.json +26 -5
  2. package/THIRDPARTY.txt +1 -1
  3. package/package.json +1 -1
  4. package/src/jquery.sap.global.js +1 -1
  5. package/src/jquery.sap.properties.js +1 -1
  6. package/src/jquery.sap.resources.js +1 -1
  7. package/src/jquery.sap.script.js +1 -1
  8. package/src/jquery.sap.storage.js +3 -3
  9. package/src/sap/base/assert.js +1 -1
  10. package/src/sap/base/strings/whitespaceReplacer.js +1 -1
  11. package/src/sap/base/util/restricted/_CancelablePromise.js +2 -2
  12. package/src/sap/base/util/restricted/_castArray.js +1 -1
  13. package/src/sap/base/util/restricted/_compact.js +1 -1
  14. package/src/sap/base/util/restricted/_curry.js +1 -1
  15. package/src/sap/base/util/restricted/_debounce.js +1 -1
  16. package/src/sap/base/util/restricted/_difference.js +1 -1
  17. package/src/sap/base/util/restricted/_differenceBy.js +1 -1
  18. package/src/sap/base/util/restricted/_differenceWith.js +1 -1
  19. package/src/sap/base/util/restricted/_flatMap.js +1 -1
  20. package/src/sap/base/util/restricted/_flatMapDeep.js +1 -1
  21. package/src/sap/base/util/restricted/_flatMapDepth.js +1 -1
  22. package/src/sap/base/util/restricted/_flatten.js +1 -1
  23. package/src/sap/base/util/restricted/_flattenDeep.js +1 -1
  24. package/src/sap/base/util/restricted/_flattenDepth.js +1 -1
  25. package/src/sap/base/util/restricted/_intersection.js +1 -1
  26. package/src/sap/base/util/restricted/_intersectionBy.js +1 -1
  27. package/src/sap/base/util/restricted/_intersectionWith.js +1 -1
  28. package/src/sap/base/util/restricted/_isEqual.js +1 -1
  29. package/src/sap/base/util/restricted/_isEqualWith.js +1 -1
  30. package/src/sap/base/util/restricted/_isNil.js +1 -1
  31. package/src/sap/base/util/restricted/_max.js +1 -1
  32. package/src/sap/base/util/restricted/_merge.js +1 -1
  33. package/src/sap/base/util/restricted/_mergeWith.js +1 -1
  34. package/src/sap/base/util/restricted/_min.js +1 -1
  35. package/src/sap/base/util/restricted/_omit.js +1 -1
  36. package/src/sap/base/util/restricted/_pick.js +1 -1
  37. package/src/sap/base/util/restricted/_pickBy.js +1 -1
  38. package/src/sap/base/util/restricted/_throttle.js +1 -1
  39. package/src/sap/base/util/restricted/_toArray.js +1 -1
  40. package/src/sap/base/util/restricted/_union.js +1 -1
  41. package/src/sap/base/util/restricted/_unionBy.js +1 -1
  42. package/src/sap/base/util/restricted/_unionWith.js +1 -1
  43. package/src/sap/base/util/restricted/_uniq.js +1 -1
  44. package/src/sap/base/util/restricted/_uniqBy.js +1 -1
  45. package/src/sap/base/util/restricted/_uniqWith.js +1 -1
  46. package/src/sap/base/util/restricted/_without.js +1 -1
  47. package/src/sap/base/util/restricted/_xor.js +1 -1
  48. package/src/sap/base/util/restricted/_xorBy.js +1 -1
  49. package/src/sap/base/util/restricted/_xorWith.js +1 -1
  50. package/src/sap/base/util/restricted/_zipObject.js +1 -1
  51. package/src/sap/base/util/restricted/_zipObjectDeep.js +1 -1
  52. package/src/sap/ui/Device.js +3 -3
  53. package/src/sap/ui/Global.js +4 -4
  54. package/src/sap/ui/base/Event.js +1 -1
  55. package/src/sap/ui/base/EventProvider.js +1 -1
  56. package/src/sap/ui/base/Interface.js +1 -1
  57. package/src/sap/ui/base/ManagedObject.js +1 -1
  58. package/src/sap/ui/base/ManagedObjectMetadata.js +1 -1
  59. package/src/sap/ui/base/Metadata.js +1 -1
  60. package/src/sap/ui/base/Object.js +1 -1
  61. package/src/sap/ui/base/ObjectPool.js +1 -1
  62. package/src/sap/ui/core/.library +2 -1
  63. package/src/sap/ui/core/BusyIndicator.js +1 -1
  64. package/src/sap/ui/core/CommandExecution.js +15 -12
  65. package/src/sap/ui/core/Component.js +31 -12
  66. package/src/sap/ui/core/ComponentContainer.js +1 -1
  67. package/src/sap/ui/core/ComponentMetadata.js +27 -12
  68. package/src/sap/ui/core/ComponentSupport.js +1 -1
  69. package/src/sap/ui/core/Configuration.js +22 -8
  70. package/src/sap/ui/core/Control.js +2 -3
  71. package/src/sap/ui/core/Core.js +95 -27
  72. package/src/sap/ui/core/CustomData.js +1 -1
  73. package/src/sap/ui/core/DeclarativeSupport.js +1 -1
  74. package/src/sap/ui/core/Element.js +1 -1
  75. package/src/sap/ui/core/ElementMetadata.js +1 -1
  76. package/src/sap/ui/core/EnabledPropagator.js +1 -1
  77. package/src/sap/ui/core/EventBus.js +1 -1
  78. package/src/sap/ui/core/ExtensionPoint.js +1 -1
  79. package/src/sap/ui/core/FocusHandler.js +2 -3
  80. package/src/sap/ui/core/Fragment.js +1 -1
  81. package/src/sap/ui/core/HTML.js +1 -1
  82. package/src/sap/ui/core/History.js +1 -1
  83. package/src/sap/ui/core/Icon.js +2 -2
  84. package/src/sap/ui/core/IndicationColorSupport.js +1 -1
  85. package/src/sap/ui/core/IntervalTrigger.js +1 -1
  86. package/src/sap/ui/core/InvisibleMessage.js +1 -1
  87. package/src/sap/ui/core/InvisibleRenderer.js +1 -1
  88. package/src/sap/ui/core/InvisibleText.js +1 -1
  89. package/src/sap/ui/core/Item.js +1 -1
  90. package/src/sap/ui/core/LabelEnablement.js +1 -1
  91. package/src/sap/ui/core/LayoutData.js +1 -1
  92. package/src/sap/ui/core/ListItem.js +1 -1
  93. package/src/sap/ui/core/LocalBusyIndicator.js +1 -1
  94. package/src/sap/ui/core/Locale.js +1 -1
  95. package/src/sap/ui/core/LocaleData.js +119 -1
  96. package/src/sap/ui/core/Manifest.js +1 -1
  97. package/src/sap/ui/core/Message.js +1 -1
  98. package/src/sap/ui/core/Popup.js +12 -14
  99. package/src/sap/ui/core/RenderManager.js +1 -1
  100. package/src/sap/ui/core/Renderer.js +1 -1
  101. package/src/sap/ui/core/ResizeHandler.js +1 -1
  102. package/src/sap/ui/core/ScrollBar.js +21 -15
  103. package/src/sap/ui/core/SeparatorItem.js +1 -1
  104. package/src/sap/ui/core/ShortcutHintsMixin.js +2 -4
  105. package/src/sap/ui/core/Title.js +1 -1
  106. package/src/sap/ui/core/TooltipBase.js +1 -1
  107. package/src/sap/ui/core/UIArea.js +3 -5
  108. package/src/sap/ui/core/UIComponent.js +1 -1
  109. package/src/sap/ui/core/UIComponentMetadata.js +1 -1
  110. package/src/sap/ui/core/ValueStateSupport.js +1 -1
  111. package/src/sap/ui/core/VariantLayoutData.js +1 -1
  112. package/src/sap/ui/core/XMLComposite.js +1 -1
  113. package/src/sap/ui/core/XMLCompositeMetadata.js +1 -1
  114. package/src/sap/ui/core/XMLTemplateProcessor.js +512 -387
  115. package/src/sap/ui/core/cache/CacheManager.js +27 -0
  116. package/src/sap/ui/core/cache/CacheManagerNOP.js +3 -0
  117. package/src/sap/ui/core/cache/LRUPersistentCache.js +74 -3
  118. package/src/sap/ui/core/cldr/ar.json +469 -1
  119. package/src/sap/ui/core/cldr/ar_EG.json +469 -1
  120. package/src/sap/ui/core/cldr/ar_SA.json +469 -1
  121. package/src/sap/ui/core/cldr/bg.json +469 -1
  122. package/src/sap/ui/core/cldr/ca.json +469 -1
  123. package/src/sap/ui/core/cldr/cs.json +469 -1
  124. package/src/sap/ui/core/cldr/cy.json +469 -1
  125. package/src/sap/ui/core/cldr/da.json +469 -1
  126. package/src/sap/ui/core/cldr/de.json +469 -1
  127. package/src/sap/ui/core/cldr/de_AT.json +469 -1
  128. package/src/sap/ui/core/cldr/de_CH.json +469 -1
  129. package/src/sap/ui/core/cldr/el.json +469 -1
  130. package/src/sap/ui/core/cldr/el_CY.json +469 -1
  131. package/src/sap/ui/core/cldr/en.json +469 -1
  132. package/src/sap/ui/core/cldr/en_AU.json +469 -1
  133. package/src/sap/ui/core/cldr/en_GB.json +469 -1
  134. package/src/sap/ui/core/cldr/en_HK.json +469 -1
  135. package/src/sap/ui/core/cldr/en_IE.json +469 -1
  136. package/src/sap/ui/core/cldr/en_IN.json +469 -1
  137. package/src/sap/ui/core/cldr/en_NZ.json +469 -1
  138. package/src/sap/ui/core/cldr/en_PG.json +469 -1
  139. package/src/sap/ui/core/cldr/en_SG.json +469 -1
  140. package/src/sap/ui/core/cldr/en_ZA.json +469 -1
  141. package/src/sap/ui/core/cldr/es.json +469 -1
  142. package/src/sap/ui/core/cldr/es_AR.json +469 -1
  143. package/src/sap/ui/core/cldr/es_BO.json +469 -1
  144. package/src/sap/ui/core/cldr/es_CL.json +469 -1
  145. package/src/sap/ui/core/cldr/es_CO.json +469 -1
  146. package/src/sap/ui/core/cldr/es_MX.json +469 -1
  147. package/src/sap/ui/core/cldr/es_PE.json +469 -1
  148. package/src/sap/ui/core/cldr/es_UY.json +469 -1
  149. package/src/sap/ui/core/cldr/es_VE.json +469 -1
  150. package/src/sap/ui/core/cldr/et.json +469 -1
  151. package/src/sap/ui/core/cldr/fa.json +469 -1
  152. package/src/sap/ui/core/cldr/fi.json +469 -1
  153. package/src/sap/ui/core/cldr/fr.json +469 -1
  154. package/src/sap/ui/core/cldr/fr_BE.json +469 -1
  155. package/src/sap/ui/core/cldr/fr_CA.json +469 -1
  156. package/src/sap/ui/core/cldr/fr_CH.json +469 -1
  157. package/src/sap/ui/core/cldr/fr_LU.json +469 -1
  158. package/src/sap/ui/core/cldr/he.json +469 -1
  159. package/src/sap/ui/core/cldr/hi.json +469 -1
  160. package/src/sap/ui/core/cldr/hr.json +469 -1
  161. package/src/sap/ui/core/cldr/hu.json +469 -1
  162. package/src/sap/ui/core/cldr/id.json +469 -1
  163. package/src/sap/ui/core/cldr/it.json +469 -1
  164. package/src/sap/ui/core/cldr/it_CH.json +469 -1
  165. package/src/sap/ui/core/cldr/ja.json +469 -1
  166. package/src/sap/ui/core/cldr/kk.json +469 -1
  167. package/src/sap/ui/core/cldr/ko.json +469 -1
  168. package/src/sap/ui/core/cldr/lt.json +469 -1
  169. package/src/sap/ui/core/cldr/lv.json +469 -1
  170. package/src/sap/ui/core/cldr/ms.json +469 -1
  171. package/src/sap/ui/core/cldr/nb.json +469 -1
  172. package/src/sap/ui/core/cldr/nl.json +469 -1
  173. package/src/sap/ui/core/cldr/nl_BE.json +469 -1
  174. package/src/sap/ui/core/cldr/pl.json +469 -1
  175. package/src/sap/ui/core/cldr/pt.json +469 -1
  176. package/src/sap/ui/core/cldr/pt_PT.json +469 -1
  177. package/src/sap/ui/core/cldr/ro.json +469 -1
  178. package/src/sap/ui/core/cldr/ru.json +469 -1
  179. package/src/sap/ui/core/cldr/ru_UA.json +469 -1
  180. package/src/sap/ui/core/cldr/sk.json +469 -1
  181. package/src/sap/ui/core/cldr/sl.json +469 -1
  182. package/src/sap/ui/core/cldr/sr.json +469 -1
  183. package/src/sap/ui/core/cldr/sr_Latn.json +469 -1
  184. package/src/sap/ui/core/cldr/sv.json +469 -1
  185. package/src/sap/ui/core/cldr/th.json +469 -1
  186. package/src/sap/ui/core/cldr/tr.json +469 -1
  187. package/src/sap/ui/core/cldr/uk.json +469 -1
  188. package/src/sap/ui/core/cldr/vi.json +469 -1
  189. package/src/sap/ui/core/cldr/zh_CN.json +470 -2
  190. package/src/sap/ui/core/cldr/zh_HK.json +470 -2
  191. package/src/sap/ui/core/cldr/zh_SG.json +470 -2
  192. package/src/sap/ui/core/cldr/zh_TW.json +469 -1
  193. package/src/sap/ui/core/delegate/ItemNavigation.js +13 -14
  194. package/src/sap/ui/core/delegate/ScrollEnablement.js +11 -7
  195. package/src/sap/ui/core/dnd/DragAndDrop.js +2 -2
  196. package/src/sap/ui/core/dnd/DragDropBase.js +1 -1
  197. package/src/sap/ui/core/dnd/DragDropInfo.js +1 -1
  198. package/src/sap/ui/core/dnd/DragInfo.js +1 -1
  199. package/src/sap/ui/core/dnd/DropInfo.js +1 -1
  200. package/src/sap/ui/core/format/DateFormat.js +41 -26
  201. package/src/sap/ui/core/format/NumberFormat.js +119 -53
  202. package/src/sap/ui/core/format/TimezoneUtil.js +48 -16
  203. package/src/sap/ui/core/hyphenation/Hyphenation.js +1 -1
  204. package/src/sap/ui/core/library.js +3 -3
  205. package/src/sap/ui/core/message/ControlMessageProcessor.js +1 -1
  206. package/src/sap/ui/core/message/Message.js +1 -1
  207. package/src/sap/ui/core/message/MessageManager.js +1 -1
  208. package/src/sap/ui/core/message/MessageParser.js +1 -1
  209. package/src/sap/ui/core/message/MessageProcessor.js +1 -1
  210. package/src/sap/ui/core/mvc/HTMLView.js +1 -1
  211. package/src/sap/ui/core/mvc/JSONView.js +1 -1
  212. package/src/sap/ui/core/mvc/JSView.js +2 -2
  213. package/src/sap/ui/core/mvc/TemplateView.js +1 -1
  214. package/src/sap/ui/core/mvc/View.js +2 -1
  215. package/src/sap/ui/core/mvc/XMLView.js +12 -20
  216. package/src/sap/ui/core/mvc/XMLViewRenderer.js +81 -62
  217. package/src/sap/ui/core/plugin/DeclarativeSupport.js +1 -1
  218. package/src/sap/ui/core/plugin/LessSupport.js +3 -3
  219. package/src/sap/ui/core/plugin/TemplatingSupport.js +1 -1
  220. package/src/sap/ui/core/postmessage/Bus.js +1 -1
  221. package/src/sap/ui/core/postmessage/confirmationDialog.js +1 -1
  222. package/src/sap/ui/core/routing/Router.js +1 -1
  223. package/src/sap/ui/core/rules/App.support.js +8 -8
  224. package/src/sap/ui/core/rules/Config.support.js +12 -12
  225. package/src/sap/ui/core/rules/Model.support.js +8 -8
  226. package/src/sap/ui/core/rules/Rendering.support.js +1 -1
  227. package/src/sap/ui/core/rules/Theming.support.js +4 -4
  228. package/src/sap/ui/core/rules/View.support.js +9 -9
  229. package/src/sap/ui/core/search/OpenSearchProvider.js +1 -1
  230. package/src/sap/ui/core/search/SearchProvider.js +1 -1
  231. package/src/sap/ui/core/service/Service.js +1 -1
  232. package/src/sap/ui/core/service/ServiceFactory.js +1 -1
  233. package/src/sap/ui/core/service/ServiceFactoryRegistry.js +1 -1
  234. package/src/sap/ui/core/support/Plugin.js +1 -1
  235. package/src/sap/ui/core/support/Support.js +2 -2
  236. package/src/sap/ui/core/support/plugins/ControlTree.js +7 -3
  237. package/src/sap/ui/core/support/plugins/Interaction.js +1 -1
  238. package/src/sap/ui/core/support/plugins/LocalStorage.js +1 -1
  239. package/src/sap/ui/core/support/plugins/Performance.js +1 -1
  240. package/src/sap/ui/core/support/plugins/Selector.js +1 -1
  241. package/src/sap/ui/core/support/plugins/TechInfo.js +1 -1
  242. package/src/sap/ui/core/support/plugins/Trace.js +1 -1
  243. package/src/sap/ui/core/support/plugins/ViewInfo.js +8 -22
  244. package/src/sap/ui/core/support/support.html +1 -1
  245. package/src/sap/ui/core/themes/base/LocalBusyIndicator.less +15 -1
  246. package/src/sap/ui/core/themes/base/base.less +4 -4
  247. package/src/sap/ui/core/themes/base/global.less +2 -0
  248. package/src/sap/ui/core/themes/sap_hcb/global.less +2 -0
  249. package/src/sap/ui/core/tmpl/DOMAttribute.js +1 -1
  250. package/src/sap/ui/core/tmpl/DOMElement.js +1 -1
  251. package/src/sap/ui/core/tmpl/HandlebarsTemplate.js +1 -1
  252. package/src/sap/ui/core/tmpl/Template.js +1 -1
  253. package/src/sap/ui/core/tmpl/TemplateControl.js +1 -1
  254. package/src/sap/ui/core/util/AsyncHintsHelper.js +1 -1
  255. package/src/sap/ui/core/util/Export.js +1 -1
  256. package/src/sap/ui/core/util/ExportCell.js +1 -1
  257. package/src/sap/ui/core/util/ExportColumn.js +1 -1
  258. package/src/sap/ui/core/util/ExportRow.js +1 -1
  259. package/src/sap/ui/core/util/ExportType.js +1 -1
  260. package/src/sap/ui/core/util/ExportTypeCSV.js +1 -1
  261. package/src/sap/ui/core/util/File.js +1 -1
  262. package/src/sap/ui/core/util/LibraryInfo.js +1 -1
  263. package/src/sap/ui/core/util/MockServer.js +2 -2
  264. package/src/sap/ui/core/util/PasteHelper.js +1 -1
  265. package/src/sap/ui/core/util/serializer/HTMLViewSerializer.js +1 -1
  266. package/src/sap/ui/core/util/serializer/Serializer.js +1 -1
  267. package/src/sap/ui/core/util/serializer/ViewSerializer.js +1 -1
  268. package/src/sap/ui/core/util/serializer/XMLViewSerializer.js +1 -1
  269. package/src/sap/ui/core/util/serializer/delegate/Delegate.js +1 -1
  270. package/src/sap/ui/core/util/serializer/delegate/HTML.js +1 -1
  271. package/src/sap/ui/core/util/serializer/delegate/XML.js +1 -1
  272. package/src/sap/ui/core/ws/ReadyState.js +1 -1
  273. package/src/sap/ui/core/ws/SapPcpWebSocket.js +1 -1
  274. package/src/sap/ui/core/ws/WebSocket.js +7 -8
  275. package/src/sap/ui/debug/ControlTree.js +1 -1
  276. package/src/sap/ui/debug/DebugEnv.js +1 -1
  277. package/src/sap/ui/debug/PropertyList.js +1 -1
  278. package/src/sap/ui/model/ClientListBinding.js +127 -21
  279. package/src/sap/ui/model/ClientModel.js +1 -1
  280. package/src/sap/ui/model/CompositeDataState.js +1 -1
  281. package/src/sap/ui/model/CompositeType.js +1 -1
  282. package/src/sap/ui/model/DataState.js +1 -1
  283. package/src/sap/ui/model/ListBinding.js +32 -13
  284. package/src/sap/ui/model/MetaModel.js +1 -1
  285. package/src/sap/ui/model/Model.js +1 -1
  286. package/src/sap/ui/model/SelectionModel.js +1 -1
  287. package/src/sap/ui/model/SimpleType.js +1 -1
  288. package/src/sap/ui/model/TreeAutoExpandMode.js +1 -1
  289. package/src/sap/ui/model/Type.js +1 -1
  290. package/src/sap/ui/model/_Helper.js +3 -1
  291. package/src/sap/ui/model/json/JSONListBinding.js +0 -58
  292. package/src/sap/ui/model/json/JSONModel.js +1 -1
  293. package/src/sap/ui/model/message/MessageListBinding.js +0 -42
  294. package/src/sap/ui/model/message/MessageModel.js +1 -1
  295. package/src/sap/ui/model/odata/ODataAnnotations.js +1 -1
  296. package/src/sap/ui/model/odata/ODataMessageParser.js +1 -1
  297. package/src/sap/ui/model/odata/ODataMetaModel.js +1 -1
  298. package/src/sap/ui/model/odata/ODataMetadata.js +1 -1
  299. package/src/sap/ui/model/odata/ODataModel.js +1 -1
  300. package/src/sap/ui/model/odata/OperationMode.js +6 -0
  301. package/src/sap/ui/model/odata/type/Boolean.js +1 -1
  302. package/src/sap/ui/model/odata/type/Byte.js +1 -1
  303. package/src/sap/ui/model/odata/type/Currency.js +1 -1
  304. package/src/sap/ui/model/odata/type/Date.js +1 -1
  305. package/src/sap/ui/model/odata/type/DateTime.js +1 -1
  306. package/src/sap/ui/model/odata/type/DateTimeBase.js +1 -1
  307. package/src/sap/ui/model/odata/type/DateTimeOffset.js +1 -1
  308. package/src/sap/ui/model/odata/type/DateTimeWithTimezone.js +1 -2
  309. package/src/sap/ui/model/odata/type/Decimal.js +1 -1
  310. package/src/sap/ui/model/odata/type/Double.js +1 -1
  311. package/src/sap/ui/model/odata/type/Guid.js +1 -1
  312. package/src/sap/ui/model/odata/type/Int.js +1 -1
  313. package/src/sap/ui/model/odata/type/Int16.js +1 -1
  314. package/src/sap/ui/model/odata/type/Int32.js +1 -1
  315. package/src/sap/ui/model/odata/type/Int64.js +1 -1
  316. package/src/sap/ui/model/odata/type/ODataType.js +1 -1
  317. package/src/sap/ui/model/odata/type/Raw.js +1 -1
  318. package/src/sap/ui/model/odata/type/SByte.js +1 -1
  319. package/src/sap/ui/model/odata/type/Single.js +1 -1
  320. package/src/sap/ui/model/odata/type/Stream.js +1 -1
  321. package/src/sap/ui/model/odata/type/String.js +1 -1
  322. package/src/sap/ui/model/odata/type/Time.js +1 -1
  323. package/src/sap/ui/model/odata/type/TimeOfDay.js +1 -1
  324. package/src/sap/ui/model/odata/type/Unit.js +1 -1
  325. package/src/sap/ui/model/odata/type/UnitMixin.js +1 -1
  326. package/src/sap/ui/model/odata/v2/Context.js +13 -4
  327. package/src/sap/ui/model/odata/v2/ODataAnnotations.js +1 -1
  328. package/src/sap/ui/model/odata/v2/ODataListBinding.js +107 -34
  329. package/src/sap/ui/model/odata/v2/ODataModel.js +70 -22
  330. package/src/sap/ui/model/odata/v2/ODataTreeBinding.js +8 -4
  331. package/src/sap/ui/model/odata/v4/Context.js +25 -1
  332. package/src/sap/ui/model/odata/v4/ODataContextBinding.js +1 -1
  333. package/src/sap/ui/model/odata/v4/ODataListBinding.js +55 -26
  334. package/src/sap/ui/model/odata/v4/ODataMetaModel.js +13 -6
  335. package/src/sap/ui/model/odata/v4/ODataModel.js +111 -5
  336. package/src/sap/ui/model/odata/v4/ODataPropertyBinding.js +1 -1
  337. package/src/sap/ui/model/odata/v4/lib/_Cache.js +74 -74
  338. package/src/sap/ui/model/odata/v4/lib/_Helper.js +109 -39
  339. package/src/sap/ui/model/odata/v4/lib/_Requestor.js +60 -29
  340. package/src/sap/ui/model/resource/ResourceModel.js +1 -1
  341. package/src/sap/ui/model/type/Boolean.js +1 -1
  342. package/src/sap/ui/model/type/Currency.js +1 -1
  343. package/src/sap/ui/model/type/Date.js +1 -1
  344. package/src/sap/ui/model/type/DateInterval.js +1 -1
  345. package/src/sap/ui/model/type/DateTime.js +1 -1
  346. package/src/sap/ui/model/type/DateTimeInterval.js +1 -1
  347. package/src/sap/ui/model/type/FileSize.js +1 -1
  348. package/src/sap/ui/model/type/Float.js +1 -1
  349. package/src/sap/ui/model/type/Integer.js +1 -1
  350. package/src/sap/ui/model/type/String.js +1 -1
  351. package/src/sap/ui/model/type/Time.js +1 -1
  352. package/src/sap/ui/model/type/TimeInterval.js +1 -1
  353. package/src/sap/ui/model/type/Unit.js +1 -1
  354. package/src/sap/ui/model/xml/XMLListBinding.js +0 -53
  355. package/src/sap/ui/model/xml/XMLModel.js +1 -1
  356. package/src/sap/ui/qunit/utils/ControlIterator.js +1 -1
  357. package/src/sap/ui/qunit/utils/MemoryLeakCheck.js +1 -1
  358. package/src/sap/ui/test/actions/Action.js +3 -3
  359. package/src/sap/ui/test/actions/Press.js +1 -1
  360. package/src/sap/ui/test/generic/TestBase.js +1 -1
  361. package/src/sap/ui/util/Storage.js +1 -1
  362. package/ui5.yaml +1 -1
@@ -125,6 +125,15 @@ function(
125
125
  */
126
126
  var CORE_NAMESPACE = "sap.ui.core";
127
127
 
128
+ /**
129
+ * XML Namespace of the mvc relevant controls in the core library.
130
+ *
131
+ * This namespace is used to identify the view tags within the sap.ui.core.mvc namespace.
132
+ * @const
133
+ * @private
134
+ */
135
+ var CORE_MVC_NAMESPACE = "sap.ui.core.mvc";
136
+
128
137
  /**
129
138
  * An XML namespace that apps can use to add custom data to a control's XML element.
130
139
  * The name of the attribute will be used as key, the value as value of a CustomData element.
@@ -168,6 +177,15 @@ function(
168
177
  */
169
178
  var PREPROCESSOR_NAMESPACE_PREFIX = "http://schemas.sap.com/sapui5/preprocessorextension/";
170
179
 
180
+ /**
181
+ * List of attributes that are declared as "special settings" in view's metadata but can be configured on View's
182
+ * root tag
183
+ *
184
+ * @const
185
+ * @private
186
+ */
187
+ var VIEW_SPECIAL_ATTRIBUTES = ['controllerName', 'resourceBundleName', 'resourceBundleUrl', 'resourceBundleLocale', 'resourceBundleAlias'];
188
+
171
189
  /**
172
190
  * Pattern that matches the names of all HTML void tags.
173
191
  * @private
@@ -184,28 +202,26 @@ function(
184
202
  function getHandleChildrenStrategy(bAsync, fnCallback) {
185
203
 
186
204
  // sync strategy ensures processing order by just being sync
187
- function syncStrategy(node, oAggregation, mAggregations, pRequireContext, oClosestBinding) {
188
- var childNode,
189
- vChild,
205
+ function syncStrategy(node, mOptions) {
206
+ var pChild,
190
207
  aChildren = [];
191
208
 
192
- for (childNode = node.firstChild; childNode; childNode = childNode.nextSibling) {
193
- vChild = fnCallback(node, oAggregation, mAggregations, childNode, false, pRequireContext, oClosestBinding);
194
- if (vChild) {
195
- aChildren.push(vChild.unwrap());
209
+ for (var i = 0; i < node.childNodes.length; i++) {
210
+ pChild = fnCallback(node, node.childNodes[i], mOptions);
211
+ if (pChild) {
212
+ aChildren.push(pChild.unwrap());
196
213
  }
197
214
  }
198
215
  return SyncPromise.resolve(aChildren);
199
216
  }
200
217
 
201
218
  // async strategy ensures processing order by chaining the callbacks
202
- function asyncStrategy(node, oAggregation, mAggregations, pRequireContext, oClosestBinding) {
203
- var childNode,
204
- pChain = Promise.resolve(),
205
- aChildPromises = [pRequireContext];
219
+ function asyncStrategy(node, mOptions) {
220
+ var pChain = Promise.resolve(),
221
+ aChildPromises = [mOptions.chain];
206
222
 
207
- for (childNode = node.firstChild; childNode; childNode = childNode.nextSibling) {
208
- pChain = pChain.then(fnCallback.bind(null, node, oAggregation, mAggregations, childNode, false, pRequireContext, oClosestBinding));
223
+ for (var i = 0; i < node.childNodes.length; i++) {
224
+ pChain = pChain.then(fnCallback.bind(null, node, node.childNodes[i], mOptions));
209
225
  aChildPromises.push(pChain);
210
226
  }
211
227
  return Promise.all(aChildPromises);
@@ -255,34 +271,19 @@ function(
255
271
  };
256
272
 
257
273
  /**
258
- * Parses only the attributes of the XML root node (View!) and fills them into the given settings object.
259
- * Children are parsed later on after the controller has been set.
260
- * TODO cannot handle event handlers in the root node
274
+ * Parses special settings that are supported on the View's root tag but not declared in View's metadata. The
275
+ * standard properties, event handlers, aggregations and associations are parsed in the same way as the child nodes
276
+ * are parsed.
261
277
  *
262
278
  * @param {Element} xmlNode the XML element representing the View
263
279
  * @param {sap.ui.core.mvc.XMLView} oView the View to consider when parsing the attributes
264
- * @param {object} mSettings the settings object which should be enriched with the suitable attributes from the XML node
265
- * @return undefined
266
280
  */
267
- XMLTemplateProcessor.parseViewAttributes = function(xmlNode, oView, mSettings) {
268
-
269
- var mAllProperties = oView.getMetadata().getAllProperties();
270
- for ( var i = 0; i < xmlNode.attributes.length; i++) {
271
- var attr = xmlNode.attributes[i];
272
- if (attr.name === 'controllerName') {
273
- oView._controllerName = attr.value;
274
- } else if (attr.name === 'resourceBundleName') {
275
- oView._resourceBundleName = attr.value;
276
- } else if (attr.name === 'resourceBundleUrl') {
277
- oView._resourceBundleUrl = attr.value;
278
- } else if (attr.name === 'resourceBundleLocale') {
279
- oView._resourceBundleLocale = attr.value;
280
- } else if (attr.name === 'resourceBundleAlias') {
281
- oView._resourceBundleAlias = attr.value;
282
- } else if (attr.name === 'class') {
283
- oView.addStyleClass(attr.value);
284
- } else if (!mSettings[attr.name] && mAllProperties[attr.name]) {
285
- mSettings[attr.name] = parseScalarType(mAllProperties[attr.name].type, attr.value, attr.name, oView._oContainingView.oController);
281
+ XMLTemplateProcessor.parseViewAttributes = function(xmlNode, oView) {
282
+ var i, attr;
283
+ for ( i = 0; i < xmlNode.attributes.length; i++) {
284
+ attr = xmlNode.attributes[i];
285
+ if (VIEW_SPECIAL_ATTRIBUTES.includes(attr.name)) {
286
+ oView["_" + attr.name] = attr.value;
286
287
  }
287
288
  }
288
289
  };
@@ -320,10 +321,11 @@ function(
320
321
  *
321
322
  * @param {Element} xmlNode the XML element representing the View/Fragment
322
323
  * @param {sap.ui.core.mvc.XMLView|sap.ui.core.Fragment} oView the View/Fragment which corresponds to the parsed XML
324
+ * @param {object} mSettings The settings object that is given to the view's factory method
323
325
  * @return {Array} an array containing Controls and/or plain HTML element strings
324
326
  */
325
- XMLTemplateProcessor.parseTemplate = function(xmlNode, oView) {
326
- return XMLTemplateProcessor.parseTemplatePromise(xmlNode, oView, false).unwrap();
327
+ XMLTemplateProcessor.parseTemplate = function(xmlNode, oView, mSettings) {
328
+ return XMLTemplateProcessor.parseTemplatePromise(xmlNode, oView, false, { settings: mSettings }).unwrap();
327
329
  };
328
330
 
329
331
  /**
@@ -339,33 +341,29 @@ function(
339
341
  XMLTemplateProcessor.parseTemplatePromise = function(xmlNode, oView, bAsync, oParseConfig) {
340
342
  return parseTemplate(xmlNode, oView, false, bAsync, oParseConfig).then(function(vResult) {
341
343
  // vResult is the result array of the XMLTP's parsing.
342
- // It contains strings like "tabs/linebreaks/..." AND control instances
343
- // Additionally it also includes ExtensionPoint placeholder objects if an ExtensionPoint is present in the top-level of the View.
344
+ // Elements in vResult can be:
345
+ // * RenderManager Call (Array)
346
+ // * Control instance (Object)
347
+ // * ExtensionPoint placeholder (Object)
344
348
 
345
349
  // we only trigger Flex for ExtensionPoints inside Views
346
- // A potential ExtensionPoint provider will resolve any ExtensionPoints with their correct content (or the default content, if not flex changes exist)
347
- if (oView.isA("sap.ui.core.mvc.View") && oView._epInfo && oView._epInfo.all.length > 0) {
348
- // wait for ExtensionPoint Provider, but resolve with original render-content array ("aResult" in parseTemplate())
349
- return fnTriggerExtensionPointProvider(bAsync, oView, {
350
- "content": oView._epInfo.all
351
- }).then(function() {
352
- // For async views all ExtensionPoints have been resolved.
353
- // Their resulting content needs to be spliced into the rendering array.
354
- // We loop backwards so we don't have to deal with index shifts (EPs can have more than 1 result control).
355
- if (Array.isArray(vResult)) {
356
- for (var i = vResult.length - 1; i >= 0; i--) {
357
- var vContent = vResult[i];
358
- if (vContent && vContent._isExtensionPoint) {
359
- var aSpliceArgs = [i, 1].concat(vContent._aControls);
360
- Array.prototype.splice.apply(vResult, aSpliceArgs);
361
- }
362
- }
350
+ // A potential ExtensionPoint provider will resolve any ExtensionPoints with their correct content (or the default content, if no flex changes exist)
351
+ if (oView.isA("sap.ui.core.mvc.View")) {
352
+ var vContent, i;
353
+ // For async views all ExtensionPoints have been resolved.
354
+ // Their resulting content needs to be spliced into the rendering array.
355
+ // We loop backwards so we don't have to deal with index shifts (EPs can have more than 1 result control).
356
+ for (i = vResult.length - 1; i >= 0; i--) {
357
+ vContent = vResult[i];
358
+
359
+ if (vContent && vContent._isExtensionPoint) {
360
+ var aSpliceArgs = [i, 1].concat(vContent._aControls);
361
+ Array.prototype.splice.apply(vResult, aSpliceArgs);
363
362
  }
364
- return vResult;
365
- });
366
- } else {
367
- return vResult;
363
+ }
368
364
  }
365
+
366
+ return vResult;
369
367
  });
370
368
  };
371
369
 
@@ -395,7 +393,7 @@ function(
395
393
 
396
394
  if (!oRequireContext[sKey] || typeof oRequireContext[sKey] !== "string") {
397
395
  // The value should be a non-empty string
398
- sErrorMessage = "core:require in XMLView contains invalide value '"
396
+ sErrorMessage = "core:require in XMLView contains invalid value '"
399
397
  + oRequireContext[sKey] + "'under key '" + sKey + "'";
400
398
  return true;
401
399
  }
@@ -580,14 +578,14 @@ function(
580
578
  close: function(tagName) {
581
579
  aResult.push(["close", [tagName]]);
582
580
  },
583
- renderControl: function(content) {
584
- aResult.push(pResultChain);
581
+ renderControl: function(pContent) {
582
+ aResult.push(pContent);
585
583
  }
586
584
  };
587
585
 
588
586
  bAsync = bAsync && !!oView._sProcessingMode;
589
587
  Log.debug("XML processing mode is " + (oView._sProcessingMode || "default") + ".", "", "XMLTemplateProcessor");
590
- Log.debug("XML will be processed " + bAsync ? "asynchronously" : "synchronously" + ".", "", "XMLTemplateProcessor");
588
+ Log.debug("XML will be processed " + (bAsync ? "asynchronously" : "synchronously") + ".", "", "XMLTemplateProcessor");
591
589
 
592
590
  var bDesignMode = sap.ui.getCore().getConfiguration().getDesignMode();
593
591
  if (bDesignMode) {
@@ -599,30 +597,13 @@ function(
599
597
  oView._oContainingView._sapui_declarativeSourceInfo.xmlRootNode
600
598
  };
601
599
  }
602
- var sCurrentName = oView.sViewName || oView._sFragmentName; // TODO: should Fragments and Views be separated here?
603
- if (!sCurrentName) {
604
- var oTopView = oView;
605
- var iLoopCounter = 0; // Make sure there are not infinite loops
606
- while (++iLoopCounter < 1000 && oTopView && oTopView !== oTopView._oContainingView) {
607
- oTopView = oTopView._oContainingView;
608
- }
609
- sCurrentName = oTopView.sViewName;
610
- }
611
-
612
- if (oView.isSubView()) {
613
- parseNode(xmlNode, true, false, pResultChain);
614
- } else {
615
- if (xmlNode.localName === "View" && xmlNode.namespaceURI !== "sap.ui.core.mvc") {
616
- // it's not <core:View>, it's <mvc:View> !!!
617
- Log.warning("XMLView root node must have the 'sap.ui.core.mvc' namespace, not '" + xmlNode.namespaceURI + "'" + (sCurrentName ? " (View name: " + sCurrentName + ")" : ""));
618
- }
619
-
600
+ if (!oView.isSubView()) {
620
601
  // define internal namespace on root node
621
602
  xmlNode.setAttributeNS(XMLNS_NAMESPACE, "xmlns:" + sInternalPrefix, UI5_INTERNAL_NAMESPACE);
622
-
623
- parseChildren(xmlNode, false, false, pResultChain);
624
603
  }
625
604
 
605
+ var bWrapped = processNode(xmlNode, pResultChain);
606
+
626
607
  // iterate aResult for Promises
627
608
  // if a Promise is found splice its resolved content at the same position in aResult
628
609
  // then start over again starting with the position of the last extracted element
@@ -654,7 +635,20 @@ function(
654
635
  // Once this Promise is resolved, we have the full view content available.
655
636
  // The final output of the parseTemplate call will be an array containing DOM Strings and UI5 Controls.
656
637
  // Flatten the array so that all promises are resolved and replaced.
657
- return pResultChain.then(resolveResultPromises);
638
+ return pResultChain
639
+ .then(resolveResultPromises)
640
+ .then(function(aResult) {
641
+ // remove the wrapper node
642
+ if (bWrapped) {
643
+ var oWrapper = xmlNode.parentNode;
644
+ oWrapper.removeChild(xmlNode);
645
+
646
+ if (oWrapper.parentNode) {
647
+ oWrapper.parentNode.replaceChild(xmlNode, oWrapper);
648
+ }
649
+ }
650
+ return aResult;
651
+ });
658
652
 
659
653
  function identity(sId) {
660
654
  return sId;
@@ -664,169 +658,84 @@ function(
664
658
  return oView._oContainingView.createId(sId);
665
659
  }
666
660
 
667
- /**
668
- * Parses an XML node that might represent a UI5 control or simple XHTML.
669
- * XHTML will be added to the aResult array as a sequence of strings,
670
- * UI5 controls will be instantiated and added as controls
671
- *
672
- * @param {Element} xmlNode the XML node to parse
673
- * @param {boolean} bRoot whether this node is the root node
674
- * @param {boolean} bIgnoreTopLevelTextNodes
675
- * @param {Promise} pRequireContext Promise which resolves with the loaded modules from require context
676
- * @returns {Promise} resolving with the content of the parsed node, which is a tree structure containing DOM Strings & UI5 Controls
677
- */
678
- function parseNode(xmlNode, bRoot, bIgnoreTopLevelTextNodes, pRequireContext) {
679
-
680
- if ( xmlNode.nodeType === 1 /* ELEMENT_NODE */ ) {
661
+ function createErrorInfo(node, vError) {
662
+ var sType = oView.getMetadata().isA("sap.ui.core.mvc.View") ? "View" : "Fragment";
663
+ var sNodeSerialization = node.outerHTML ? node.cloneNode(false).outerHTML : node.textContent;
681
664
 
682
- var sLocalName = localName(xmlNode);
683
- var bXHTML = xmlNode.namespaceURI === XHTML_NAMESPACE;
684
- if (bXHTML || xmlNode.namespaceURI === SVG_NAMESPACE) {
685
- // determine ID
686
- var sId = xmlNode.getAttribute("id");
687
- if ( sId == null ) {
688
- sId = bRoot === true ? oView.getId() : undefined;
689
- } else {
690
- sId = getId(oView, xmlNode);
691
- }
692
- if ( sLocalName === "style" ) {
693
- // We need to remove the namespace prefix from style nodes
694
- // otherwise the style element's content will be output as text and not evaluated as CSS
695
- // We do this by manually 'cloning' the style without the NS prefix
696
-
697
- // original node values
698
- var aAttributes = xmlNode.attributes; // array-like 'NamedNodeMap'
699
- var sTextContent = xmlNode.textContent;
700
-
701
- // 'clone'
702
- xmlNode = document.createElement(sLocalName);
703
- xmlNode.textContent = sTextContent;
704
-
705
- // copy all non-prefixed attributes
706
- // -> prefixed attributes are invalid HTML
707
- for (var j = 0; j < aAttributes.length; j++) {
708
- var oAttr = aAttributes[j];
709
- if (!oAttr.prefix) {
710
- xmlNode.setAttribute(oAttr.name, oAttr.value);
711
- }
712
- }
713
- // avoid encoding of style content by writing the whole tag as unsafeHtml
714
- // for compatibility reasons, apply the same ID rewriting as for other tags
715
- if ( sId != null ) {
716
- xmlNode.setAttribute("id", sId);
717
- }
718
- if ( bRoot === true ) {
719
- xmlNode.setAttribute("data-sap-ui-preserve", oView.getId());
720
- }
721
- rm.unsafeHtml(xmlNode.outerHTML);
722
- return;
723
- }
724
- // write opening tag
725
- var bVoid = rVoidTags.test(sLocalName);
726
- if ( bVoid ) {
727
- rm.voidStart(sLocalName, sId);
728
- } else {
729
- rm.openStart(sLocalName, sId);
730
- }
731
- // write attributes
732
- for (var i = 0; i < xmlNode.attributes.length; i++) {
733
- var attr = xmlNode.attributes[i];
734
- if ( attr.name !== "id" ) {
735
- rm.attr(bXHTML ? attr.name.toLowerCase() : attr.name, attr.value);
736
- }
737
- }
738
- if ( bRoot === true ) {
739
- rm.attr("data-sap-ui-preserve", oView.getId());
740
- }
741
- if ( bVoid ) {
742
- rm.voidEnd();
743
- if ( xmlNode.firstChild ) {
744
- Log.error("Content of void HTML element '" + sLocalName + "' will be ignored");
745
- }
746
- } else {
747
- rm.openEnd();
665
+ return "Error found in " + sType + " (id: '" + oView.getId() + "').\nXML node: '" + sNodeSerialization + "':\n" + vError;
666
+ }
748
667
 
749
- // write children
750
- // For HTMLTemplateElement nodes, skip the associated DocumentFragment node
751
- var oContent = xmlNode instanceof HTMLTemplateElement ? xmlNode.content : xmlNode;
752
- parseChildren(oContent, false, false, pRequireContext);
753
- rm.close(sLocalName);
754
- }
668
+ function normalizeRootNode(node) {
669
+ var sNodeName = localName(node),
670
+ oWrapper;
671
+
672
+ // Normalize the view content by wrapping it with either a "View" tag or a "FragmentDefinition" tag to
673
+ // simplify the parsing process
674
+ if (oView.isA("sap.ui.core.mvc.XMLView") && (node.namespaceURI === XHTML_NAMESPACE || node.namespaceURI === SVG_NAMESPACE)) {
675
+ // XHTML or SVG nodes are placed into a sub view without having "View" as root tag
676
+ // Wrap the content into a "View" node
677
+ oWrapper = node.ownerDocument.createElementNS(CORE_MVC_NAMESPACE, "View");
678
+ } else if (oView.isA("sap.ui.core.Fragment") && (sNodeName !== "FragmentDefinition" || node.namespaceURI !== CORE_NAMESPACE)) {
679
+ // Wrap the content into a "FragmentDefinition" node for single control node
680
+ oWrapper = node.ownerDocument.createElementNS(CORE_NAMESPACE, "FragmentDefinition");
681
+ }
755
682
 
756
- } else if (sLocalName === "FragmentDefinition" && xmlNode.namespaceURI === CORE_NAMESPACE) {
757
- // a Fragment element - which is not turned into a control itself. Only its content is parsed.
758
- parseChildren(xmlNode, false, true, pRequireContext);
759
- // TODO: check if this branch is required or can be handled by the below one
683
+ if (oWrapper) {
684
+ var oOldParent = node.parentNode;
760
685
 
761
- } else {
686
+ if (oOldParent) {
687
+ oOldParent.replaceChild(oWrapper, node);
688
+ }
689
+ oWrapper.appendChild(node);
690
+ }
762
691
 
763
- // assumption: an ELEMENT_NODE with non-XHTML namespace is an SAPUI5 control and the namespace equals the library name
764
- pResultChain = pResultChain.then(function() {
765
- // Chaining the Promises as we need to make sure the order in which the XML DOM nodes are processed is fixed (depth-first, pre-order).
766
- // The order of processing (and Promise resolution) is mandatory for keeping the order of the UI5 Controls' aggregation fixed and compatible.
767
- return createControlOrExtension(xmlNode, pRequireContext).then(function(aChildControls) {
768
- for (var i = 0; i < aChildControls.length; i++) {
769
- var oChild = aChildControls[i];
770
-
771
- // only views have a content aggregation
772
- if (oView.getMetadata().hasAggregation("content")) {
773
- // track extensionpoint information for root-level children of the view
774
- oView._epInfo = oView._epInfo || {
775
- contentControlsCount: 0,
776
- last: null,
777
- all: []
778
- };
779
-
780
- // child node is a placeholder for an ExtensionPoint
781
- // only in Flexibility scenario if an ExtensionProvider is given!
782
- if (oChild._isExtensionPoint) {
783
- oChild.index = oView._epInfo.contentControlsCount;
784
- oChild.targetControl = oView;
785
- oChild.aggregationName = "content";
786
- if (oView._epInfo.last) {
787
- oView._epInfo.last._nextSibling = oChild;
788
- }
789
- oView._epInfo.last = oChild;
790
- oView._epInfo.all.push(oChild);
791
- } else {
792
- // regular UI5 Controls can be added to the content aggregation directly
793
- oView._epInfo.contentControlsCount++;
794
- oView.addAggregation("content", oChild);
795
- }
692
+ return oWrapper;
693
+ }
796
694
 
797
- // can oView really have an association called "content"?
798
- } else if (oView.getMetadata().hasAssociation(("content"))) {
799
- oView.addAssociation("content", oChild);
800
- }
801
- }
802
- return aChildControls;
803
- });
804
- });
805
- rm.renderControl(pResultChain);
695
+ function processNode(node, pChain) {
696
+ var bWrapped = false,
697
+ sCurrentName = oView.sViewName || oView._sFragmentName,
698
+ oNewRoot, sNodeName;
806
699
 
700
+ if (!sCurrentName) {
701
+ var oTopView = oView;
702
+ var iLoopCounter = 0; // Make sure there are not infinite loops
703
+ while (++iLoopCounter < 1000 && oTopView && oTopView !== oTopView._oContainingView) {
704
+ oTopView = oTopView._oContainingView;
807
705
  }
706
+ sCurrentName = oTopView.sViewName;
707
+ }
808
708
 
809
- } else if (xmlNode.nodeType === 3 /* TEXT_NODE */ && !bIgnoreTopLevelTextNodes) {
709
+ oNewRoot = normalizeRootNode(node);
710
+ if (oNewRoot) {
711
+ node = oNewRoot;
712
+ bWrapped = true;
713
+ }
810
714
 
811
- rm.text(xmlNode.textContent);
715
+ sNodeName = localName(node);
716
+ if (oView.isA("sap.ui.core.mvc.XMLView")) {
717
+ if ((sNodeName !== "View" && sNodeName !== "XMLView") || node.namespaceURI !== CORE_MVC_NAMESPACE) {
718
+ Log.error("XMLView's root node must be 'View' or 'XMLView' and have the namespace 'sap.ui.core.mvc'" + (sCurrentName ? " (View name: " + sCurrentName + ")" : ""));
719
+ }
720
+ // createRegularControls
721
+ pResultChain = pChain.then(function() {
722
+ return createRegularControls(node, oView.getMetadata().getClass(), pChain, null, { rootArea: true, rootNode: true });
723
+ });
724
+ } else {
725
+ var handleChildren = getHandleChildrenStrategy(bAsync, function(node, childNode, mOptions) {
726
+ if (childNode.nodeType === 1 /* Element Node*/) {
727
+ return createControls(childNode, mOptions.chain, null /*closest binding*/, undefined /* aggregation info*/, { rootArea: true });
728
+ }
729
+ });
812
730
 
813
- }
814
- }
731
+ pResultChain = pChain.then(function() {
732
+ return handleChildren(node, {
733
+ chain: pChain
734
+ });
735
+ });
815
736
 
816
- /**
817
- * Parses the children of an XML node.
818
- *
819
- * @param {Element} xmlNode the xml node which will be parsed
820
- * @param {boolean} bRoot
821
- * @param {boolean} bIgnoreToplevelTextNodes
822
- * @param {Promise} pRequireContext Promise which resolves with the loaded modules from require context
823
- * @returns {Promise[]} each resolving to the according child nodes content
824
- */
825
- function parseChildren(xmlNode, bRoot, bIgnoreToplevelTextNodes, pRequireContext) {
826
- var children = xmlNode.childNodes;
827
- for (var i = 0; i < children.length; i++) {
828
- parseNode(children[i], bRoot, bIgnoreToplevelTextNodes, pRequireContext);
829
737
  }
738
+ return bWrapped;
830
739
  }
831
740
 
832
741
  /**
@@ -886,56 +795,200 @@ function(
886
795
  *
887
796
  * @param {Element} node The current XMLNode which is being processed
888
797
  * @param {Promise} pRequireContext Promise which resolves with the loaded modules from require context
798
+ * @param {object} [oClosestBinding] Information on the binding that is closest to currently processed control
799
+ * node. Used by the flex extension-point provider to correctly trigger aggregation updates. This is necessary
800
+ * for extension-points that are inside a template control of an aggregation.
801
+ * @param {Object} [oAggregation] The information of the aggregation to which the control being processed will be added
802
+ * @param {object} [oConfig] The config object that contains information which is forwarded during the recursive processing
803
+ * @param {boolean} [oConfig.rootArea=false] Indicates whether it's processing the root area of an XMLView
804
+ * @param {boolean} [oConfig.rootNode=false] Indicates whether the <code>node</code> is the root node of an XMLView's content
889
805
  * @return {Promise} resolving to an array with 0..n controls
890
806
  * @private
891
807
  */
892
- function createControls(node, pRequireContext, oClosestBinding) {
893
- // differentiate between SAPUI5 and plain-HTML children
894
- if (node.namespaceURI === XHTML_NAMESPACE || node.namespaceURI === SVG_NAMESPACE ) {
895
- var id = node.attributes['id'] ? node.attributes['id'].textContent || node.attributes['id'].text : null;
808
+ function createControls(node, pRequireContext, oClosestBinding, oAggregation, oConfig) {
809
+ var bRootArea = oConfig && oConfig.rootArea,
810
+ bRootNodeInSubView = oConfig && oConfig.rootNode && oView.isSubView(),
811
+ sLocalName = localName(node),
812
+ bRenderingRelevant = bRootArea && (oView.isA("sap.ui.core.Fragment") || (oAggregation && oAggregation.name === "content")),
813
+ pResult, i;
814
+
815
+ if ( node.nodeType === 1 /* ELEMENT_NODE */ ) {
816
+ // differentiate between SAPUI5 and plain-HTML children
817
+ if (node.namespaceURI === XHTML_NAMESPACE || node.namespaceURI === SVG_NAMESPACE ) {
818
+ if (bRootArea) {
819
+ if (oAggregation && oAggregation.name !== "content") {
820
+ Log.error(createErrorInfo(node, "XHTML nodes can only be added to the 'content' aggregation and not to the '" + oAggregation.name + "' aggregation."));
821
+ return SyncPromise.resolve([]);
822
+ }
896
823
 
897
- if (bEnrichFullIds) {
898
- return XMLTemplateProcessor.enrichTemplateIdsPromise(node, oView, bAsync).then(function(){
899
- // do not create controls
900
- return [];
901
- });
902
- } else {
903
- // plain HTML node - create a new View control
904
- // creates a view instance, but makes sure the new view receives the correct owner component
905
- var fnCreateView = function (oViewClass) {
906
- var mViewParameters = {
907
- id: id ? getId(oView, node, id) : undefined,
908
- xmlNode: node,
909
- containingView: oView._oContainingView,
910
- processingMode: oView._sProcessingMode // add processing mode, so it can be propagated to subviews inside the HTML block
911
- };
912
- // running with owner component
913
- if (oView.fnScopedRunWithOwner) {
914
- return oView.fnScopedRunWithOwner(function () {
824
+ if (oConfig && oConfig.contentBound) {
825
+ throw new Error(createErrorInfo(node, "No XHTML or SVG node is allowed because the 'content' aggregation is bound."));
826
+ }
827
+
828
+ var bXHTML = node.namespaceURI === XHTML_NAMESPACE;
829
+
830
+ // determine ID
831
+ var sId = node.getAttribute("id");
832
+ if ( sId != null ) {
833
+ sId = getId(oView, node);
834
+ } else {
835
+ sId = bRootNodeInSubView ? oView.getId() : undefined;
836
+ }
837
+
838
+ if ( sLocalName === "style" ) {
839
+ // We need to remove the namespace prefix from style nodes
840
+ // otherwise the style element's content will be output as text and not evaluated as CSS
841
+ // We do this by manually 'cloning' the style without the namespace prefix
842
+
843
+ // original node values
844
+ var aAttributes = node.attributes; // array-like 'NamedNodeMap'
845
+ var sTextContent = node.textContent;
846
+
847
+ // 'clone'
848
+ node = document.createElement(sLocalName);
849
+ node.textContent = sTextContent;
850
+
851
+ // copy all non-prefixed attributes
852
+ // -> prefixed attributes are invalid HTML
853
+ for (i = 0; i < aAttributes.length; i++) {
854
+ var oAttr = aAttributes[i];
855
+ if (!oAttr.prefix) {
856
+ node.setAttribute(oAttr.name, oAttr.value);
857
+ }
858
+ }
859
+ // avoid encoding of style content by writing the whole tag as unsafeHtml
860
+ // for compatibility reasons, apply the same ID rewriting as for other tags
861
+ if ( sId != null ) {
862
+ node.setAttribute("id", sId);
863
+ }
864
+ if ( bRootNodeInSubView ) {
865
+ node.setAttribute("data-sap-ui-preserve", oView.getId());
866
+ }
867
+ rm.unsafeHtml(node.outerHTML);
868
+ return SyncPromise.resolve([]);
869
+ }
870
+ // write opening tag
871
+ var bVoid = rVoidTags.test(sLocalName);
872
+ if ( bVoid ) {
873
+ rm.voidStart(sLocalName, sId);
874
+ } else {
875
+ rm.openStart(sLocalName, sId);
876
+ }
877
+ // write attributes
878
+ for (i = 0; i < node.attributes.length; i++) {
879
+ var attr = node.attributes[i];
880
+ if ( attr.name !== "id" ) {
881
+ rm.attr(bXHTML ? attr.name.toLowerCase() : attr.name, attr.value);
882
+ }
883
+ }
884
+ if ( bRootNodeInSubView ) {
885
+ rm.attr("data-sap-ui-preserve", oView.getId());
886
+ }
887
+ if ( bVoid ) {
888
+ rm.voidEnd();
889
+ if ( node.firstChild ) {
890
+ Log.error("Content of void HTML element '" + sLocalName + "' will be ignored");
891
+ }
892
+ } else {
893
+ rm.openEnd();
894
+
895
+ // write children
896
+ // For HTMLTemplateElement nodes, skip the associated DocumentFragment node
897
+ var oContent = node instanceof HTMLTemplateElement ? node.content : node;
898
+
899
+ var handleChildren = getHandleChildrenStrategy(bAsync, function (node, childNode, mOptions) {
900
+ return createControls(childNode, mOptions.chain, mOptions.closestBinding, mOptions.aggregation, mOptions.config);
901
+ });
902
+
903
+ pResult = handleChildren(oContent, {
904
+ chain: pRequireContext,
905
+ closestBinding: oClosestBinding,
906
+ aggregation: oAggregation,
907
+ config: { rootArea: bRootArea }
908
+ });
909
+
910
+
911
+ return pResult.then(function(aResults) {
912
+ rm.close(sLocalName);
913
+
914
+ // aResults can contain the following elements:
915
+ // * require context object
916
+ // * array of control instance(s)
917
+ // * undefined
918
+ return aResults.reduce(function(acc, vControls) {
919
+ if (Array.isArray(vControls)) {
920
+ vControls.forEach(function(oControl) {
921
+ acc.push(oControl);
922
+ });
923
+ }
924
+ return acc;
925
+ }, []);
926
+ });
927
+ }
928
+ } else {
929
+ var id = node.attributes['id'] ? node.attributes['id'].textContent || node.attributes['id'].text : null;
930
+
931
+ if (bEnrichFullIds) {
932
+ return XMLTemplateProcessor.enrichTemplateIdsPromise(node, oView, bAsync).then(function(){
933
+ // do not create controls
934
+ return [];
935
+ });
936
+ } else {
937
+ // plain HTML node - create a new View control
938
+ // creates a view instance, but makes sure the new view receives the correct owner component
939
+ var fnCreateView = function (oViewClass) {
940
+ var mViewParameters = {
941
+ id: id ? getId(oView, node, id) : undefined,
942
+ xmlNode: node,
943
+ containingView: oView._oContainingView,
944
+ processingMode: oView._sProcessingMode // add processing mode, so it can be propagated to subviews inside the HTML block
945
+ };
946
+ // running with owner component
947
+ if (oView.fnScopedRunWithOwner) {
948
+ return oView.fnScopedRunWithOwner(function () {
949
+ return new oViewClass(mViewParameters);
950
+ });
951
+ }
952
+ // no owner component
953
+ // (or fully sync path, which handles the owner propagation on a higher level)
915
954
  return new oViewClass(mViewParameters);
955
+ };
956
+
957
+ return pRequireContext.then(function() {
958
+ if (bAsync) {
959
+ return new Promise(function (resolve, reject) {
960
+ sap.ui.require(["sap/ui/core/mvc/XMLView"], function(XMLView) {
961
+ resolve([fnCreateView(XMLView)]);
962
+ }, reject);
963
+ });
964
+ } else {
965
+ var XMLView = sap.ui.requireSync("sap/ui/core/mvc/XMLView"); // legacy-relevant: Sync path
966
+ return [fnCreateView(XMLView)];
967
+ }
916
968
  });
917
969
  }
918
- // no owner component
919
- // (or fully sync path, which handles the owner propagation on a higher level)
920
- return new oViewClass(mViewParameters);
921
- };
970
+ }
922
971
 
923
- if (bAsync) {
924
- return new Promise(function (resolve, reject) {
925
- sap.ui.require(["sap/ui/core/mvc/XMLView"], function(XMLView) {
926
- resolve([fnCreateView(XMLView)]);
927
- }, reject);
928
- });
929
- } else {
930
- var XMLView = sap.ui.requireSync("sap/ui/core/mvc/XMLView"); // legacy-relevant: Sync path
931
- return SyncPromise.resolve([fnCreateView(XMLView)]);
972
+ } else {
973
+ pResult = createControlOrExtension(node, pRequireContext, oClosestBinding);
974
+ if (bRenderingRelevant) {
975
+ rm.renderControl(pResult);
932
976
  }
977
+ // non-HTML (SAPUI5) control
978
+ // we must return the result in either bRootArea=true or the bRootArea=false case because we use the result
979
+ // to add the control to the aggregation of its parent control
980
+ return pResult;
981
+ }
982
+ } else if (node.nodeType === 3 /* TEXT_NODE */ && bRenderingRelevant) {
983
+ if (!oConfig || !oConfig.contentBound) {
984
+ // content aggregation isn't bound
985
+ rm.text(node.textContent);
986
+ } else if (node.textContent.trim()) {
987
+ throw new Error(createErrorInfo(node, "Text node isn't allowed because the 'content' aggregation is bound."));
933
988
  }
934
-
935
- } else {
936
- // non-HTML (SAPUI5) control
937
- return createControlOrExtension(node, pRequireContext, oClosestBinding);
938
989
  }
990
+
991
+ return SyncPromise.resolve([]);
939
992
  }
940
993
 
941
994
  /**
@@ -945,6 +998,9 @@ function(
945
998
  *
946
999
  * @param {Element} node The current XMLNode which is being processed
947
1000
  * @param {Promise} pRequireContext Promise which resolves with the loaded modules from require context
1001
+ * @param {object} [oClosestBinding] Information on the binding that is closest to currently processed control
1002
+ * node. Used by the flex extension-point provider to correctly trigger aggregation updates. This is necessary
1003
+ * for extension-points that are inside a template control of an aggregation.
948
1004
  * @return {Promise} resolving to an array with 0..n controls created from a node
949
1005
  * @private
950
1006
  */
@@ -1027,10 +1083,20 @@ function(
1027
1083
  * One control for regular controls, zero for ExtensionPoints without configured extension and
1028
1084
  * n controls for multi-root Fragments.
1029
1085
  *
1086
+ * @param {Element} node The current XMLNode which is being processed
1087
+ * @param {function} oClass The constructor of the control that is currently being processed
1088
+ * @param {Promise} pRequireContext Promise which resolves with the loaded modules from require context
1089
+ * @param {object} [oClosestBinding] Information on the binding that is closest to currently processed control
1090
+ * node. Used by the flex extension-point provider to correctly trigger aggregation updates. This is necessary
1091
+ * for extension-points that are inside a template control of an aggregation.
1092
+ * @param {object} [oConfig] The config object that contains information which is forwarded during the recursive processing
1093
+ * @param {boolean} [oConfig.rootArea=false] Indicates whether it's processing the root area of an XMLView
1094
+ * @param {boolean} [oConfig.rootNode=false] Indicates whether the <code>node</code> is the root node of an XMLView's content
1095
+ *
1030
1096
  * @return {Promise} resolving to an array with 0..n controls created from a node
1031
1097
  * @private
1032
1098
  */
1033
- function createRegularControls(node, oClass, pRequireContext, oClosestBinding) {
1099
+ function createRegularControls(node, oClass, pRequireContext, oClosestBinding, oConfig) {
1034
1100
  var ns = node.namespaceURI,
1035
1101
  mSettings = {},
1036
1102
  mAggregationsWithExtensionPoints = {},
@@ -1044,10 +1110,12 @@ function(
1044
1110
  // 2. Associations
1045
1111
  // -> might refer to controls inside the node, which have been removed earlier when the StashedControl was created
1046
1112
  // 3. Events
1047
- bStashedControl = node.getAttribute("stashed") === "true";
1048
-
1113
+ bStashedControl = node.getAttribute("stashed") === "true",
1114
+ bRootArea = oConfig && oConfig.rootArea,
1115
+ bViewRootNode = oConfig && oConfig.rootNode,
1116
+ oRequireContext;
1049
1117
 
1050
- // remove stashed attribute as it is an uknown property.
1118
+ // remove stashed attribute as it is an unknown property.
1051
1119
  if (!bEnrichFullIds) {
1052
1120
  node.removeAttribute("stashed");
1053
1121
  }
@@ -1056,10 +1124,16 @@ function(
1056
1124
  return SyncPromise.resolve([]);
1057
1125
  }
1058
1126
 
1127
+ if (bViewRootNode) {
1128
+ // although the 'id' isn't needed for mSettings object because the view instance is already created,
1129
+ // it's still needed for the closestBinding info object
1130
+ mSettings.id = oView.getId();
1131
+ }
1132
+
1059
1133
  var oMetadata = oClass.getMetadata();
1060
1134
  var mKnownSettings = oMetadata.getAllSettings();
1061
1135
 
1062
- var pSelfRequireContext = parseAndLoadRequireContext(node, bAsync);
1136
+ var pSelfRequireContext = !bRootArea ? parseAndLoadRequireContext(node, bAsync) : undefined;
1063
1137
 
1064
1138
  // create new promise only when the current node has core:require defined
1065
1139
  if (pSelfRequireContext) {
@@ -1074,6 +1148,8 @@ function(
1074
1148
  oRequireModules = null;
1075
1149
  }
1076
1150
 
1151
+ oRequireContext = oRequireModules;
1152
+
1077
1153
  if (!bEnrichFullIds) {
1078
1154
  for (var i = 0; i < node.attributes.length; i++) {
1079
1155
  var attr = node.attributes[i],
@@ -1082,13 +1158,17 @@ function(
1082
1158
  oInfo = mKnownSettings[sName],
1083
1159
  sValue = attr.value;
1084
1160
 
1161
+ if (bViewRootNode && VIEW_SPECIAL_ATTRIBUTES.includes(sName)) {
1162
+ continue;
1163
+ }
1164
+
1085
1165
  // apply the value of the attribute to a
1086
1166
  // * property,
1087
1167
  // * association (id of the control),
1088
1168
  // * event (name of the function in the controller) or
1089
1169
  // * CustomData element (namespace-prefixed attribute)
1090
1170
 
1091
- if (sName === "id") {
1171
+ if (sName === "id" && !bViewRootNode) { // "id" attribute on View's root node isn't supported
1092
1172
  // special handling for ID
1093
1173
  mSettings[sName] = getId(oView, node, sValue);
1094
1174
 
@@ -1255,15 +1335,10 @@ function(
1255
1335
  // Errors caught here are expected UI5 issues, e.g. DataType errors, broken BindingSyntax, missing event handler functions etc.
1256
1336
  // we enrich the error message with XML information, e.g. the node causing the issue
1257
1337
  if (!oError.isEnriched) {
1258
- var sType = oView.getMetadata().isA("sap.ui.core.mvc.View") ? "View" : "Fragment";
1259
- var sNodeSerialization = node && node.cloneNode(false).outerHTML;
1260
1338
  // Logging the error like this cuts away the stack trace,
1261
1339
  // but provides better information for applications.
1262
1340
  // For Framework debugging, we would have to look at the error object anyway.
1263
- oError = new Error(
1264
- "Error found in " + sType + " (id: '" + oView.getId() + "').\nXML node: '" + sNodeSerialization + "':\n" +
1265
- oError
1266
- );
1341
+ oError = new Error(createErrorInfo(node, oError));
1267
1342
  oError.isEnriched = true;
1268
1343
 
1269
1344
  // TODO: Can be enriched with additional info for a support rule (not yet implemented)
@@ -1272,7 +1347,7 @@ function(
1272
1347
 
1273
1348
  // [COMPATIBILITY]
1274
1349
  // sync: we just log the error and keep on processing
1275
- // asnyc: throw the error, so the parseTempate Promise will reject
1350
+ // asnyc: throw the error, so the parseTemplate Promise will reject
1276
1351
  if (bAsync && oView._sProcessingMode !== XMLProcessingMode.SequentialLegacy) {
1277
1352
  throw oError;
1278
1353
  }
@@ -1291,8 +1366,13 @@ function(
1291
1366
  * @return {Promise} resolving to an array with 0..n controls created from a node
1292
1367
  * @private
1293
1368
  */
1294
- function handleChild(node, oAggregation, mAggregations, childNode, bActivate, pRequireContext, oClosestBinding) {
1295
- var oNamedAggregation,
1369
+ function handleChild(node, childNode, mOptions) {
1370
+ var oAggregation = mOptions.aggregation,
1371
+ mAggregations = mOptions.allAggregations,
1372
+ pRequireContext = mOptions.chain,
1373
+ oClosestBinding = mOptions.closestBinding,
1374
+ oConfig = mOptions.config,
1375
+ oNamedAggregation,
1296
1376
  fnCreateStashedControl;
1297
1377
 
1298
1378
  // inspect only element nodes
@@ -1300,22 +1380,28 @@ function(
1300
1380
 
1301
1381
  if (childNode.namespaceURI === XML_COMPOSITE_NAMESPACE) {
1302
1382
  mSettings[localName(childNode)] = childNode.querySelector("*");
1303
- return;
1383
+ return undefined;
1304
1384
  }
1305
1385
  // check for a named aggregation (must have the same namespace as the parent and an aggregation with the same name must exist)
1306
1386
  oNamedAggregation = childNode.namespaceURI === ns && mAggregations && mAggregations[localName(childNode)];
1307
1387
 
1308
1388
  if (oNamedAggregation) {
1309
1389
  // the children of the current childNode are aggregated controls (or HTML) below the named aggregation
1310
- return handleChildren(childNode, oNamedAggregation, false, pRequireContext, oClosestBinding);
1390
+ return handleChildren(childNode, {
1391
+ aggregation: oNamedAggregation,
1392
+ allAggregations: null,
1393
+ chain: pRequireContext,
1394
+ closestBinding: oClosestBinding,
1395
+ config: oConfig
1396
+ });
1311
1397
  } else if (oAggregation) {
1312
1398
  // TODO consider moving this to a place where HTML and SVG nodes can be handled properly
1313
1399
  // create a StashedControl for inactive controls, which is not placed in an aggregation
1314
- if (!bActivate && childNode.getAttribute("stashed") === "true" && !bEnrichFullIds) {
1400
+ if (childNode.getAttribute("stashed") === "true" && !bEnrichFullIds) {
1315
1401
  var oStashedNode = childNode;
1316
- // remove child-nodes...
1402
+ // clone the node and remove all descendants
1317
1403
  childNode = childNode.cloneNode();
1318
- // remove stashed attribute as it is an uknown property.
1404
+ // remove stashed attribute as it is an unknown property.
1319
1405
  oStashedNode.removeAttribute("stashed");
1320
1406
 
1321
1407
  fnCreateStashedControl = function() {
@@ -1331,7 +1417,12 @@ function(
1331
1417
  bAsync = false;
1332
1418
 
1333
1419
  try {
1334
- return handleChild(node, oAggregation, mAggregations, oStashedNode, true, pRequireContext, oClosestBinding).unwrap();
1420
+ return handleChild(node, oStashedNode, {
1421
+ aggregation: oAggregation,
1422
+ allAggregations: mAggregations,
1423
+ chain: SyncPromise.resolve(oRequireContext),
1424
+ closestBinding: oClosestBinding
1425
+ }).unwrap();
1335
1426
  } finally {
1336
1427
  // EVO-Todo:revert back to the original async/sync behavior
1337
1428
  // if we moved to the sync path for the stashed control, we might now go back to the async path.
@@ -1353,19 +1444,24 @@ function(
1353
1444
  setUI5Attribute(childNode, "invisible");
1354
1445
  }
1355
1446
 
1356
- // whether the created controls will be the template for a list binding
1357
1447
  if ( mSettings[oAggregation.name] &&
1358
- mSettings[oAggregation.name].path &&
1448
+ // whether the created controls will be the template for a list binding
1359
1449
  typeof mSettings[oAggregation.name].path === "string") {
1360
1450
  oClosestBinding = {
1361
1451
  aggregation: oAggregation.name,
1362
1452
  id: mSettings.id
1363
1453
  };
1454
+
1455
+ // mark that the content aggregation of the View node is bound
1456
+ if (bViewRootNode && oAggregation.name === "content") {
1457
+ oConfig = oConfig || {};
1458
+ oConfig.contentBound = true;
1459
+ }
1364
1460
  }
1365
1461
 
1366
1462
  // child node name does not equal an aggregation name,
1367
1463
  // so this child must be a control (or HTML) which is aggregated below the DEFAULT aggregation
1368
- return createControls(childNode, pRequireContext, oClosestBinding).then(function(aControls) {
1464
+ return createControls(childNode, pRequireContext, oClosestBinding, oAggregation, oConfig).then(function(aControls) {
1369
1465
  for (var j = 0; j < aControls.length; j++) {
1370
1466
  var oControl = aControls[j];
1371
1467
  // append the child to the aggregation
@@ -1414,14 +1510,17 @@ function(
1414
1510
  }
1415
1511
  return aControls;
1416
1512
  });
1417
- } else if (localName(node) !== "FragmentDefinition" || node.namespaceURI !== CORE_NAMESPACE) { // children of FragmentDefinitions are ok, they need no aggregation
1418
- throw new Error("Cannot add direct child without default aggregation defined for control " + oMetadata.getElementName());
1513
+ } else {
1514
+ throw new Error(createErrorInfo(childNode, "Cannot add direct child without default aggregation defined for control " + oMetadata.getElementName()));
1419
1515
  }
1420
-
1421
1516
  } else if (childNode.nodeType === 3 /* TEXT_NODE */) {
1422
- var sTextContent = childNode.textContent || childNode.text;
1423
- if (sTextContent && sTextContent.trim()) { // whitespace would be okay
1424
- throw new Error("Cannot add text nodes as direct child of an aggregation. For adding text to an aggregation, a surrounding html tag is needed: " + sTextContent.trim());
1517
+ if (oConfig && oConfig.rootArea) {
1518
+ createControls(childNode, pRequireContext, oClosestBinding, oAggregation, oConfig);
1519
+ } else {
1520
+ var sTextContent = childNode.textContent || childNode.text;
1521
+ if (sTextContent && sTextContent.trim()) { // whitespace would be okay
1522
+ throw new Error(createErrorInfo(childNode, "Cannot add text nodes as direct child of an aggregation. For adding text to an aggregation, a surrounding html tag is needed."));
1523
+ }
1425
1524
  }
1426
1525
  } // other nodes types are silently ignored
1427
1526
 
@@ -1431,7 +1530,13 @@ function(
1431
1530
  var oAggregation = oMetadata.getDefaultAggregation();
1432
1531
  var mAggregations = oMetadata.getAllAggregations();
1433
1532
 
1434
- return handleChildren(node, oAggregation, mAggregations, pRequireContext, oClosestBinding).then(function() {
1533
+ return handleChildren(node, {
1534
+ aggregation: oAggregation,
1535
+ allAggregations: mAggregations,
1536
+ chain: pRequireContext,
1537
+ closestBinding: oClosestBinding,
1538
+ config: oConfig
1539
+ }).then(function() {
1435
1540
  // apply the settings to the control
1436
1541
  var vNewControlInstance;
1437
1542
  var pProvider = SyncPromise.resolve();
@@ -1441,103 +1546,123 @@ function(
1441
1546
  var oOwnerComponent = Component.getOwnerComponentFor(oView);
1442
1547
  var bIsAsyncComponent = oOwnerComponent && oOwnerComponent.isA("sap.ui.core.IAsyncContentCreation");
1443
1548
 
1444
- if (bEnrichFullIds && node.hasAttribute("id")) {
1445
- setId(oView, node);
1446
- } else if (!bEnrichFullIds) {
1447
- if (oClass.getMetadata().isA("sap.ui.core.mvc.View")) {
1448
- var fnCreateViewInstance = function () {
1449
- if (!oClass._sType && !mSettings.viewName) {
1450
- // Add module view name
1451
- mSettings.viewName = "module:" + oClass.getMetadata().getName().replace(/\./g, "/");
1452
- }
1453
-
1454
- // If the view is owned by an async-component we can propagate the asynchronous creation behavior to the nested views
1455
- if (bIsAsyncComponent && bAsync) {
1456
- // legacy check: async=false is not supported with an async-component
1457
- if (mSettings.async === false) {
1458
- throw new Error(
1459
- "A nested view contained in a Component implementing 'sap.ui.core.IAsyncContentCreation' is processed asynchronously by default and cannot be processed synchronously.\n" +
1460
- "Affected Component '" + oOwnerComponent.getMetadata().getComponentName() + "' and View '" + mSettings.viewName + "'."
1461
- );
1462
- }
1549
+ if (bEnrichFullIds) {
1550
+ if (!bRootArea && node.hasAttribute("id")) {
1551
+ setId(oView, node);
1552
+ }
1553
+ } else if (!bViewRootNode && oClass.getMetadata().isA("sap.ui.core.mvc.View")) {
1554
+ var fnCreateViewInstance = function () {
1555
+ if (!oClass._sType && !mSettings.viewName) {
1556
+ // Add module view name
1557
+ mSettings.viewName = "module:" + oClass.getMetadata().getName().replace(/\./g, "/");
1558
+ }
1463
1559
 
1464
- mSettings.type = oClass._sType || sType;
1465
- pInstanceCreated = View.create(mSettings);
1466
- } else {
1467
- // Pass processingMode to nested XMLViews
1468
- if (oClass.getMetadata().isA("sap.ui.core.mvc.XMLView") && oView._sProcessingMode) {
1469
- mSettings.processingMode = oView._sProcessingMode;
1470
- }
1471
- return View._create(mSettings, undefined, oClass._sType || sType);
1560
+ // If the view is owned by an async-component we can propagate the asynchronous creation behavior to the nested views
1561
+ if (bIsAsyncComponent && bAsync) {
1562
+ // legacy check: async=false is not supported with an async-component
1563
+ if (mSettings.async === false) {
1564
+ throw new Error(
1565
+ "A nested view contained in a Component implementing 'sap.ui.core.IAsyncContentCreation' is processed asynchronously by default and cannot be processed synchronously.\n" +
1566
+ "Affected Component '" + oOwnerComponent.getMetadata().getComponentName() + "' and View '" + mSettings.viewName + "'."
1567
+ );
1472
1568
  }
1473
- };
1474
1569
 
1475
- // for views having a factory function defined we use the factory function!
1476
- if (oView.fnScopedRunWithOwner) {
1477
- // We need to use the already created scoped runWithOwner function from the outer view instance.
1478
- // This way, the nested views are receiving the correct Owner component, across asynchronous calls.
1479
- vNewControlInstance = oView.fnScopedRunWithOwner(fnCreateViewInstance);
1570
+ mSettings.type = oClass._sType || sType;
1571
+ pInstanceCreated = View.create(mSettings);
1480
1572
  } else {
1481
- vNewControlInstance = fnCreateViewInstance();
1573
+ // Pass processingMode to nested XMLViews
1574
+ if (oClass.getMetadata().isA("sap.ui.core.mvc.XMLView") && oView._sProcessingMode) {
1575
+ mSettings.processingMode = oView._sProcessingMode;
1576
+ }
1577
+ return View._create(mSettings, undefined, oClass._sType || sType);
1482
1578
  }
1579
+ };
1483
1580
 
1484
- } else if (oClass.getMetadata().isA("sap.ui.core.Fragment") && bAsync) {
1581
+ // for views having a factory function defined we use the factory function!
1582
+ if (oView.fnScopedRunWithOwner) {
1583
+ // We need to use the already created scoped runWithOwner function from the outer view instance.
1584
+ // This way, the nested views are receiving the correct Owner component, across asynchronous calls.
1585
+ vNewControlInstance = oView.fnScopedRunWithOwner(fnCreateViewInstance);
1586
+ } else {
1587
+ vNewControlInstance = fnCreateViewInstance();
1588
+ }
1485
1589
 
1486
- // Pass processingMode to any fragments except JS
1487
- // XML / HTML fragments: might include nested views / fragments,
1488
- // which are processed asynchronously. Therefore the processingMode is needed
1489
- // JS fragments: might include synchronously or asynchronously created content. Nevertheless, the execution of the
1490
- // content creation is not in the scope of the xml template processor, therefore the processing mode is not needed
1491
- if (sType !== ViewType.JS) {
1492
- mSettings.processingMode = oView._sProcessingMode;
1493
- }
1590
+ } else if (oClass.getMetadata().isA("sap.ui.core.Fragment") && bAsync) {
1494
1591
 
1495
- var sFragmentPath = "sap/ui/core/Fragment";
1496
- var Fragment = sap.ui.require(sFragmentPath);
1592
+ // Pass processingMode to any fragments except JS
1593
+ // XML / HTML fragments: might include nested views / fragments,
1594
+ // which are processed asynchronously. Therefore the processingMode is needed
1595
+ // JS fragments: might include synchronously or asynchronously created content. Nevertheless, the execution of the
1596
+ // content creation is not in the scope of the xml template processor, therefore the processing mode is not needed
1597
+ if (sType !== ViewType.JS) {
1598
+ mSettings.processingMode = oView._sProcessingMode;
1599
+ }
1497
1600
 
1498
- // call Fragment.load with mSettings.name
1499
- mSettings.name = mSettings.name || mSettings.fragmentName;
1601
+ var sFragmentPath = "sap/ui/core/Fragment";
1602
+ var Fragment = sap.ui.require(sFragmentPath);
1500
1603
 
1501
- if (Fragment) {
1502
- pInstanceCreated = Fragment.load(mSettings);
1503
- } else {
1504
- pInstanceCreated = new Promise(function (resolve, reject) {
1505
- sap.ui.require([sFragmentPath], function (Fragment) {
1506
- Fragment.load(mSettings).then(function (oFragmentContent) {
1507
- resolve(oFragmentContent);
1508
- });
1509
- }, reject);
1510
- });
1511
- }
1512
- } else {
1513
- // call the control constructor with the according owner in scope
1514
- var fnCreateInstance = function() {
1515
- var oInstance;
1516
-
1517
- // the scoped runWithOwner function is only during ASYNC processing!
1518
- if (oView.fnScopedRunWithOwner) {
1604
+ // call Fragment.load with mSettings.name
1605
+ mSettings.name = mSettings.name || mSettings.fragmentName;
1519
1606
 
1520
- oInstance = oView.fnScopedRunWithOwner(function () {
1521
- var oInstance = new oClass(mSettings);
1522
- return oInstance;
1607
+ if (Fragment) {
1608
+ pInstanceCreated = Fragment.load(mSettings);
1609
+ } else {
1610
+ pInstanceCreated = new Promise(function (resolve, reject) {
1611
+ sap.ui.require([sFragmentPath], function (Fragment) {
1612
+ Fragment.load(mSettings).then(function (oFragmentContent) {
1613
+ resolve(oFragmentContent);
1523
1614
  });
1524
- } else {
1525
- oInstance = new oClass(mSettings);
1615
+ }, reject);
1616
+ });
1617
+ }
1618
+ } else {
1619
+ // call the control constructor with the according owner in scope
1620
+ var fnCreateInstance = function() {
1621
+ var oInstance;
1622
+
1623
+ if (bViewRootNode) {
1624
+ oInstance = oView;
1625
+ if (!bAsync) {
1626
+ // oParseConfig.settings: the settings object that is given to the factory method
1627
+ // mSettings: the settings object that contains the properties parsed from View tag
1628
+ //
1629
+ // In sync case, mSettings is applied before the oParseConfig.settings. In order to make
1630
+ // the mSettings win against the oParseConfig.settings, the properties that exist in
1631
+ // both objects are merged into the oParseConfig.settings with the value taken from
1632
+ // mSettings and they are then deleted from mSettings.
1633
+ if (oParseConfig && oParseConfig.settings) {
1634
+ Object.keys(mSettings).forEach(function(sKey) {
1635
+ if (oParseConfig.settings.hasOwnProperty(sKey)) {
1636
+ oParseConfig.settings[sKey] = mSettings[sKey];
1637
+ delete mSettings[sKey];
1638
+ }
1639
+ });
1640
+ }
1526
1641
  }
1642
+ oView.applySettings(mSettings);
1643
+ } else if (oView.fnScopedRunWithOwner) {
1644
+ // the scoped runWithOwner function is only during ASYNC processing!
1645
+ oInstance = oView.fnScopedRunWithOwner(function () {
1646
+ var oInstance = new oClass(mSettings);
1647
+ return oInstance;
1648
+ });
1649
+ } else {
1650
+ oInstance = new oClass(mSettings);
1651
+ }
1527
1652
 
1528
- // check if we need to hand the ExtensionPoint info to the ExtensionProvider
1529
- pProvider = fnTriggerExtensionPointProvider(bAsync, oInstance, mAggregationsWithExtensionPoints);
1653
+ // check if we need to hand the ExtensionPoint info to the ExtensionProvider
1654
+ pProvider = fnTriggerExtensionPointProvider(bAsync, oInstance, mAggregationsWithExtensionPoints);
1530
1655
 
1531
- return oInstance;
1532
- };
1656
+ return oInstance;
1657
+ };
1533
1658
 
1534
- if (oParseConfig && oParseConfig.fnRunWithPreprocessor) {
1535
- vNewControlInstance = oParseConfig.fnRunWithPreprocessor(fnCreateInstance);
1536
- } else {
1537
- vNewControlInstance = fnCreateInstance();
1538
- }
1659
+ if (oParseConfig && oParseConfig.fnRunWithPreprocessor) {
1660
+ vNewControlInstance = oParseConfig.fnRunWithPreprocessor(fnCreateInstance);
1661
+ } else {
1662
+ vNewControlInstance = fnCreateInstance();
1539
1663
  }
1540
1664
  }
1665
+
1541
1666
  return pInstanceCreated.then(function (vContent) {
1542
1667
  return vContent || vNewControlInstance;
1543
1668
  }).then(function (vFinalInstance) {
@@ -1665,7 +1790,7 @@ function(
1665
1790
  oCtx = oBinding;
1666
1791
  oBinding = {parts: [oCtx]};
1667
1792
  } else {
1668
- //check the text Arrangments
1793
+ //check the text Arrangements
1669
1794
  checkFormatter(oBinding.formatter.textFragments);
1670
1795
  //only allow a number at the binding
1671
1796
  }