@ui5/builder 3.5.1 → 4.0.0

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 (32) hide show
  1. package/CHANGELOG.md +39 -3
  2. package/CONTRIBUTING.md +1 -1
  3. package/README.md +6 -6
  4. package/jsdoc.json +7 -2
  5. package/lib/lbt/bundle/Builder.js +155 -113
  6. package/lib/lbt/bundle/ResolvedBundleDefinition.js +11 -17
  7. package/lib/processors/bundlers/moduleBundler.js +19 -8
  8. package/lib/processors/jsdoc/apiIndexGenerator.js +1 -1
  9. package/lib/processors/jsdoc/jsdocGenerator.js +4 -11
  10. package/lib/processors/jsdoc/lib/package.json +3 -0
  11. package/lib/processors/jsdoc/lib/ui5/template/{publish.cjs → publish.js} +1 -1
  12. package/lib/processors/jsdoc/sdkTransformer.js +1 -1
  13. package/lib/processors/manifestEnhancer.js +420 -0
  14. package/lib/processors/minifier.js +5 -1
  15. package/lib/tasks/buildThemes.js +4 -0
  16. package/lib/tasks/bundlers/generateBundle.js +11 -2
  17. package/lib/tasks/bundlers/generateComponentPreload.js +15 -8
  18. package/lib/tasks/bundlers/generateFlexChangesBundle.js +1 -2
  19. package/lib/tasks/bundlers/generateLibraryPreload.js +11 -8
  20. package/lib/tasks/bundlers/generateStandaloneAppBundle.js +40 -21
  21. package/lib/tasks/bundlers/utils/applyDefaultsToBundleDefinition.js +35 -0
  22. package/lib/tasks/enhanceManifest.js +32 -0
  23. package/lib/tasks/generateCachebusterInfo.js +1 -2
  24. package/lib/tasks/generateThemeDesignerResources.js +1 -2
  25. package/lib/tasks/generateVersionInfo.js +3 -1
  26. package/lib/tasks/taskRepository.js +2 -1
  27. package/lib/tasks/transformBootstrapHtml.js +2 -3
  28. package/package.json +20 -21
  29. /package/lib/processors/jsdoc/lib/{createIndexFiles.cjs → createIndexFiles.js} +0 -0
  30. /package/lib/processors/jsdoc/lib/{transformApiJson.cjs → transformApiJson.js} +0 -0
  31. /package/lib/processors/jsdoc/lib/ui5/{plugin.cjs → plugin.js} +0 -0
  32. /package/lib/processors/jsdoc/lib/ui5/template/utils/{versionUtil.cjs → versionUtil.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -2,16 +2,51 @@
2
2
  All notable changes to this project will be documented in this file.
3
3
  This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
4
4
 
5
- A list of unreleased changes can be found [here](https://github.com/SAP/ui5-builder/compare/v3.5.1...HEAD).
5
+ A list of unreleased changes can be found [here](https://github.com/SAP/ui5-builder/compare/v4.0.0...HEAD).
6
+
7
+ <a name="v4.0.0"></a>
8
+ ## [v4.0.0] - 2024-07-23
9
+ ### Breaking Changes
10
+ - Drop node v21 support [`7b27171`](https://github.com/SAP/ui5-builder/commit/7b2717166686aeef8d19b1f3134ef4f39de25a80)
11
+ - Discontinue bundling of JavaScript modules as string [`7691b08`](https://github.com/SAP/ui5-builder/commit/7691b08c4cd8abc7fe3922ec913f80dca372ba4f)
12
+ - Task API arguments rename ([#995](https://github.com/SAP/ui5-builder/issues/995)) [`d1f87e0`](https://github.com/SAP/ui5-builder/commit/d1f87e0cb8b65005b034ff00b7e0d66f4a5d279e)
13
+ - Require Node.js 20.11.x/>=21.2.0 and npm >=10 [`b76ff75`](https://github.com/SAP/ui5-builder/commit/b76ff7588d65c5b5ff8fb9861a3562680e8c2e74)
14
+ - **Bundling:** Enforce usage of sap.ui.predefine instead function wrappers ([#1021](https://github.com/SAP/ui5-builder/issues/1021)) [`4bda728`](https://github.com/SAP/ui5-builder/commit/4bda7289383e8645556c68976a05db0ab5698a2b)
15
+
16
+ ### Dependency Updates
17
+ - Bump rimraf from 5.0.8 to 6.0.1 [`2b4f309`](https://github.com/SAP/ui5-builder/commit/2b4f3094107bfa7ace18091731fe2f048b233754)
18
+ - Bump terser from 5.29.1 to 5.29.2 ([#1000](https://github.com/SAP/ui5-builder/issues/1000)) [`2b6da9e`](https://github.com/SAP/ui5-builder/commit/2b6da9ed131ab21c18fdbd9a7c7328dee83bd41c)
19
+ - Bump espree from 9.6.1 to 10.0.1 [`08eb716`](https://github.com/SAP/ui5-builder/commit/08eb7165d638ccf3b078eeb3feed763765821f53)
20
+ - Bump terser from 5.27.1 to 5.27.2 ([#991](https://github.com/SAP/ui5-builder/issues/991)) [`204145d`](https://github.com/SAP/ui5-builder/commit/204145d8db2a0f76d134206b33fbef3bf1edabbf)
21
+ - Bump workerpool from 6.5.1 to 9.1.0 [`b78a70c`](https://github.com/SAP/ui5-builder/commit/b78a70cf1adec6b78d78593898942f0c7c47edca)
22
+
23
+ ### Features
24
+ - Apply default values to bunde definitions for standard tasks ([#1033](https://github.com/SAP/ui5-builder/issues/1033)) [`4178e1a`](https://github.com/SAP/ui5-builder/commit/4178e1a0315ad16b7774183a18e326f8c52f5f44)
25
+ - **Bundle 'require' section with async flag for specVersion:** 4.0 ([#1042](https://github.com/SAP/ui5-builder/issues/1042)) [`dfa67fe`](https://github.com/SAP/ui5-builder/commit/dfa67feb91b7de0d61c2713eafa639f001484d9b)
26
+ - **bundle/Builder:** Support async require sections and conditional core boot [`e421e2f`](https://github.com/SAP/ui5-builder/commit/e421e2ff7e604d9035b86d666ebaf75d29212332)
27
+ - **manifest.json:** Auto-fill supportedLocales [`b085634`](https://github.com/SAP/ui5-builder/commit/b085634555193acc669ed37e8e4b817b9798698b)
28
+
29
+ ### BREAKING CHANGE
30
+
31
+ Created bundles use sap.ui.predefine instead function wrappers. For
32
+ projects this is a compatible change. Only the produced bundle content
33
+ changes.
34
+
35
+ Task API `namespace` option got renamed to `projectNamespace`
36
+
37
+ JIRA: CPOUI5FOUNDATION-802
38
+ Relates to: https://github.com/SAP/ui5-tooling/issues/701
39
+
40
+ Support for older Node.js and npm releases has been dropped.
41
+ Only Node.js 20.11.x and >=21.2.0 as well as npm v10 or higher are supported.
6
42
 
7
43
  <a name="v3.5.1"></a>
8
44
  ## [v3.5.1] - 2024-07-22
9
45
  ### Bug Fixes
10
46
  - **generateThemeDesignerResources:** Allow core .theming in sources ([#1062](https://github.com/SAP/ui5-builder/issues/1062)) [`dda3011`](https://github.com/SAP/ui5-builder/commit/dda30114461314e81da43bd739e709186744f592)
11
47
 
12
-
13
48
  <a name="v3.5.0"></a>
14
- ## [v3.5.0] - 2024-06-24
49
+ ## [v3.5.0] - 2024-06-21
15
50
  ### Features
16
51
  - ES2023 Support [`097049d`](https://github.com/SAP/ui5-builder/commit/097049daeec5c54c2d5e858b12e0c54c826ff663)
17
52
 
@@ -884,6 +919,7 @@ to load the custom bundle file instead.
884
919
 
885
920
  ### Features
886
921
  - Add ability to configure component preloads and custom bundles [`2241e5f`](https://github.com/SAP/ui5-builder/commit/2241e5ff98fd95f1f80cc74959655ae7a9c660e7)
922
+ [v4.0.0]: https://github.com/SAP/ui5-builder/compare/v3.3.0...v4.0.0
887
923
  [v3.5.1]: https://github.com/SAP/ui5-builder/compare/v3.5.0...v3.5.1
888
924
  [v3.5.0]: https://github.com/SAP/ui5-builder/compare/v3.4.1...v3.5.0
889
925
  [v3.4.1]: https://github.com/SAP/ui5-builder/compare/v3.4.0...v3.4.1
package/CONTRIBUTING.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # Contributing to the UI5 Tooling
2
2
 
3
- See CONTRIBUTING.md in the [SAP/ui5-tooling](https://github.com/SAP/ui5-tooling/blob/v3/CONTRIBUTING.md) repository.
3
+ See CONTRIBUTING.md in the [SAP/ui5-tooling](https://github.com/SAP/ui5-tooling/blob/main/CONTRIBUTING.md) repository.
package/README.md CHANGED
@@ -1,24 +1,24 @@
1
- ![UI5 icon](https://raw.githubusercontent.com/SAP/ui5-tooling/v3/docs/images/UI5_logo_wide.png)
1
+ ![UI5 icon](https://raw.githubusercontent.com/SAP/ui5-tooling/main/docs/images/UI5_logo_wide.png)
2
2
 
3
3
  # ui5-builder
4
4
  > Modules for building UI5 projects
5
5
  > Part of the [UI5 Tooling](https://github.com/SAP/ui5-tooling)
6
6
 
7
7
  [![REUSE status](https://api.reuse.software/badge/github.com/SAP/ui5-builder)](https://api.reuse.software/info/github.com/SAP/ui5-builder)
8
- [![Build Status](https://dev.azure.com/sap/opensource/_apis/build/status/SAP.ui5-builder?branchName=v3)](https://dev.azure.com/sap/opensource/_build/latest?definitionId=26&branchName=v3)
8
+ [![Build Status](https://dev.azure.com/sap/opensource/_apis/build/status/SAP.ui5-builder?branchName=main)](https://dev.azure.com/sap/opensource/_build/latest?definitionId=26&branchName=main)
9
9
  [![npm Package Version](https://badge.fury.io/js/%40ui5%2Fbuilder.svg)](https://www.npmjs.com/package/@ui5/builder)
10
10
  [![Coverage Status](https://coveralls.io/repos/github/SAP/ui5-builder/badge.svg)](https://coveralls.io/github/SAP/ui5-builder)
11
11
 
12
12
  ## Documentation
13
- UI5 Builder documentation can be found here: [sap.github.io/ui5-tooling](https://sap.github.io/ui5-tooling/v3/pages/Builder/)
13
+ UI5 Builder documentation can be found here: [sap.github.io/ui5-tooling](https://sap.github.io/ui5-tooling/v4/pages/Builder/)
14
14
 
15
- The UI5 Builder API Reference can be found here: [`@ui5/builder`](https://sap.github.io/ui5-tooling/v3/api/)
15
+ The UI5 Builder API Reference can be found here: [`@ui5/builder`](https://sap.github.io/ui5-tooling/v4/api/)
16
16
 
17
17
  ## Contributing
18
- Please check our [Contribution Guidelines](https://github.com/SAP/ui5-tooling/blob/v3/CONTRIBUTING.md).
18
+ Please check our [Contribution Guidelines](https://github.com/SAP/ui5-tooling/blob/main/CONTRIBUTING.md).
19
19
 
20
20
  ## Support
21
- Please follow our [Contribution Guidelines](https://github.com/SAP/ui5-tooling/blob/v3/CONTRIBUTING.md#report-an-issue) on how to report an issue.
21
+ Please follow our [Contribution Guidelines](https://github.com/SAP/ui5-tooling/blob/main/CONTRIBUTING.md#report-an-issue) on how to report an issue.
22
22
 
23
23
  Please report issues in the main [UI5 Tooling](https://github.com/SAP/ui5-tooling) repository.
24
24
 
package/jsdoc.json CHANGED
@@ -4,7 +4,12 @@
4
4
  },
5
5
  "source": {
6
6
  "include": ["README.md"],
7
- "exclude": ["lib/lbt/utils/JSTokenizer.js"],
7
+ "exclude": [
8
+ "lib/lbt/utils/JSTokenizer.js",
9
+ "lib/processors/jsdoc/lib/ui5/plugin.js",
10
+ "lib/processors/jsdoc/lib/ui5/template/publish.js",
11
+ "lib/processors/jsdoc/lib/ui5/template/utils/versionUtil.js"
12
+ ],
8
13
  "includePattern": ".+\\.js$",
9
14
  "excludePattern": "(node_modules(\\\\|/))"
10
15
  },
@@ -28,7 +33,7 @@
28
33
  "openGraph": {
29
34
  "title": "UI5 Tooling - API Reference",
30
35
  "type": "website",
31
- "image": "https://sap.github.io/ui5-tooling/v3/images/UI5_logo_wide.png",
36
+ "image": "https://sap.github.io/ui5-tooling/v4/images/UI5_logo_wide.png",
32
37
  "site_name": "UI5 Tooling - API Reference",
33
38
  "url": "https://sap.github.io/ui5-tooling/"
34
39
  },
@@ -16,6 +16,7 @@ import BundleSplitter from "./AutoSplitter.js";
16
16
  import {SectionType} from "./BundleDefinition.js";
17
17
  import BundleWriter from "./BundleWriter.js";
18
18
  import {getLogger} from "@ui5/logger";
19
+ import semver from "semver";
19
20
  const log = getLogger("lbt:bundle:Builder");
20
21
 
21
22
  const sourceMappingUrlPattern = /\/\/# sourceMappingURL=(\S+)\s*$/;
@@ -35,7 +36,6 @@ function makeStringLiteral(str) {
35
36
  return strReplacements[char];
36
37
  }) + "'";
37
38
  }
38
-
39
39
  function removeHashbang(str) {
40
40
  return str.replace(/^#!(.*)/, "");
41
41
  }
@@ -44,54 +44,69 @@ function isEmptyBundle(resolvedBundle) {
44
44
  return resolvedBundle.sections.every((section) => section.modules.length === 0);
45
45
  }
46
46
 
47
- const EVOBundleFormat = {
48
- beforePreloads(section) {
49
- return `sap.ui.require.preload({\n`;
50
- },
47
+ class BundleBuilder {
48
+ constructor(pool, targetUi5CoreVersion, allowStringBundling) {
49
+ this.pool = pool;
50
+ this.resolver = new BundleResolver(pool);
51
+ this.splitter = new BundleSplitter(pool, this.resolver);
52
+ this.targetUi5CoreVersion = targetUi5CoreVersion;
53
+ this.targetUi5CoreVersionMajor = undefined;
54
+ this.allowStringBundling = allowStringBundling;
55
+ }
56
+
57
+ getUi5MajorVersion() {
58
+ if (this.targetUi5CoreVersionMajor !== undefined) {
59
+ return this.targetUi5CoreVersionMajor;
60
+ }
61
+
62
+ if (this.targetUi5CoreVersion && semver.valid(this.targetUi5CoreVersion)) {
63
+ this.targetUi5CoreVersionMajor = semver.major(this.targetUi5CoreVersion);
64
+ } else {
65
+ // Assume legacy version if unable to determine the version
66
+ this.targetUi5CoreVersionMajor = null;
67
+ }
68
+ return this.targetUi5CoreVersionMajor;
69
+ }
51
70
 
52
- afterPreloads(section) {
71
+ generateAfterPreloads(section) {
53
72
  let str = `}`;
54
73
  if ( section.name ) {
55
74
  str += `,"${section.name}"`;
56
75
  }
57
76
  str += `);\n`;
58
77
  return str;
59
- },
78
+ }
60
79
 
61
- beforeBundleInfo() {
62
- return "sap.ui.loader.config({bundlesUI5:{\n";
63
- },
80
+ generateRequire(modules) {
81
+ const requireCallback = this.determineRequireCallback(modules) ?? "";
82
+ return `sap.ui.require([${
83
+ modules.map(($) => `"${toRequireJSName($)}"`).join(",\n")
84
+ }]${requireCallback});\n`;
85
+ }
64
86
 
65
- afterBundleInfo() {
66
- return "}});\n";
67
- },
87
+ determineRequireCallback(modules) {
88
+ if (this.getUi5MajorVersion() >= 2) {
89
+ // Starting with UI5 2.0.0, method Core.boot does not exist anymore
90
+ return;
91
+ }
92
+ const coreModuleIndex = modules.indexOf(MODULE__SAP_UI_CORE_CORE);
93
+ if (coreModuleIndex === -1) {
94
+ return;
95
+ }
96
+ return `, (${
97
+ modules.map((m, i) => i === coreModuleIndex ? `Core` : `_m${i}`)
98
+ }) => Core.boot?.()`;
99
+ }
68
100
 
69
- requireSync(moduleName) {
101
+ generateRequireSync(moduleName) {
70
102
  return `sap.ui.requireSync("${toRequireJSName(moduleName)}");\n`;
71
- },
103
+ }
72
104
 
73
- shouldDecorate(resolvedModule) {
105
+ executesLoaderOrCore(resolvedModule) {
74
106
  return resolvedModule.executes(MODULE__UI5LOADER) ||
75
107
  resolvedModule.executes(MODULE__UI5LOADER_AUTOCONFIG) ||
76
108
  resolvedModule.executes(MODULE__JQUERY_SAP_GLOBAL) ||
77
109
  resolvedModule.executes(MODULE__SAP_UI_CORE_CORE);
78
- },
79
-
80
- beforeDepCache(outW) {
81
- outW.writeln(`sap.ui.loader.config({depCacheUI5:{`);
82
- },
83
-
84
- afterDepCache(outW) {
85
- outW.writeln(`}});`);
86
- }
87
- };
88
-
89
- class BundleBuilder {
90
- constructor(pool) {
91
- this.pool = pool;
92
- this.resolver = new BundleResolver(pool);
93
- this.splitter = new BundleSplitter(pool, this.resolver);
94
- this.targetBundleFormat = null;
95
110
  }
96
111
 
97
112
  async createBundle(module, options) {
@@ -121,13 +136,10 @@ class BundleBuilder {
121
136
  this.options.sourceMap = true;
122
137
  }
123
138
 
124
- // Since UI5 Tooling 3.0: Always use modern API
125
- this.targetBundleFormat = EVOBundleFormat;
126
-
127
139
  // when decorateBootstrapModule is false,
128
140
  // we don't write the optimized flag and don't write the try catch wrapper
129
141
  this.shouldDecorate = this.options.decorateBootstrapModule &&
130
- this.targetBundleFormat.shouldDecorate(resolvedModule);
142
+ this.executesLoaderOrCore(resolvedModule);
131
143
  // TODO is the following condition ok or should the availability of jquery.sap.global.js be configurable?
132
144
  this.jqglobalAvailable = !resolvedModule.containsGlobal;
133
145
  this.openModule(resolvedModule.name);
@@ -161,7 +173,7 @@ class BundleBuilder {
161
173
 
162
174
  this.closeModule(resolvedModule);
163
175
 
164
- const bundleInfo = await resolvedModule.createModuleInfo(this.pool);
176
+ const bundleInfo = await resolvedModule.createModuleInfo(this.pool, this.allowStringBundling);
165
177
  bundleInfo.size = this.outW.length;
166
178
 
167
179
  return {
@@ -199,11 +211,14 @@ class BundleBuilder {
199
211
  }
200
212
 
201
213
  closeModule(resolvedModule) {
202
- if ( resolvedModule.containsCore ) {
214
+ if ( resolvedModule.containsCoreSync ) {
215
+ if ( this.getUi5MajorVersion() >= 2 ) {
216
+ throw new Error("Requiring sap/ui/core/Core synchronously is not supported as of UI5 Version 2");
217
+ }
203
218
  this.outW.ensureNewLine(); // for clarity and to avoid issues with single line comments
204
219
  this.writeWithSourceMap(
205
220
  `// as this module contains the Core, we ensure that the Core has been booted\n` +
206
- `sap.ui.getCore().boot && sap.ui.getCore().boot();`);
221
+ `sap.ui.getCore?.().boot?.();`);
207
222
  }
208
223
  if ( this.shouldDecorate && this.options.addTryCatchRestartWrapper ) {
209
224
  this.outW.ensureNewLine(); // for clarity and to avoid issues with single line comments
@@ -217,7 +232,7 @@ class BundleBuilder {
217
232
  }
218
233
  }
219
234
 
220
- addSection(section) {
235
+ async addSection(section) {
221
236
  this.ensureRawDeclarations();
222
237
 
223
238
  switch (section.mode) {
@@ -225,15 +240,15 @@ class BundleBuilder {
225
240
  // do nothing
226
241
  return undefined; // nothing to wait for
227
242
  case SectionType.Raw:
228
- return this.writeRaw(section);
243
+ return await this.writeRaw(section);
229
244
  case SectionType.Preload:
230
- return this.writePreloadFunction(section);
245
+ return await this.writePreloadFunction(section);
231
246
  case SectionType.BundleInfo:
232
- return this.writeBundleInfos([section]);
247
+ return await this.writeBundleInfos([section]);
233
248
  case SectionType.Require:
234
- return this.writeRequires(section);
249
+ return await this.writeRequires(section);
235
250
  case SectionType.DepCache:
236
- return this.writeDepCache(section);
251
+ return await this.writeDepCache(section);
237
252
  default:
238
253
  throw new Error("unknown section mode " + section.mode);
239
254
  }
@@ -308,7 +323,7 @@ class BundleBuilder {
308
323
 
309
324
  await this.rewriteAMDModules(sequence);
310
325
  if ( sequence.length > 0 ) {
311
- this.writeWithSourceMap(this.targetBundleFormat.beforePreloads(section));
326
+ this.writeWithSourceMap(`sap.ui.require.preload({\n`);
312
327
  let i = 0;
313
328
  for ( const module of sequence ) {
314
329
  const resource = await this.pool.findResourceWithInfo(module);
@@ -316,7 +331,6 @@ class BundleBuilder {
316
331
  if ( i>0 ) {
317
332
  outW.writeln(",");
318
333
  }
319
- // this.beforeWritePreloadModule(module, resource.info, resource);
320
334
  outW.write(`\t"${module.toString()}":`);
321
335
  outW.startSegment(module);
322
336
  await this.writePreloadModule(module, resource.info, resource);
@@ -331,10 +345,8 @@ class BundleBuilder {
331
345
  if ( i > 0 ) {
332
346
  outW.writeln();
333
347
  }
334
- outW.write(this.targetBundleFormat.afterPreloads(section));
348
+ outW.write(this.generateAfterPreloads(section));
335
349
  }
336
-
337
- // this.afterWriteFunctionPreloadSection();
338
350
  }
339
351
 
340
352
  beforeWriteFunctionPreloadSection(sequence) {
@@ -380,59 +392,56 @@ class BundleBuilder {
380
392
  }
381
393
 
382
394
  async rewriteAMDModules(sequence) {
383
- if ( this.options.usePredefineCalls ) {
384
- const outW = this.outW;
385
-
386
- const remaining = [];
387
- for ( const moduleName of sequence ) {
388
- if ( /\.js$/.test(moduleName) ) {
389
- // console.log("Processing " + moduleName);
390
- const resource = await this.pool.findResourceWithInfo(moduleName);
391
- let moduleContent = (await resource.buffer()).toString();
392
- moduleContent = removeHashbang(moduleContent);
393
- let moduleSourceMap;
394
- if (this.options.sourceMap) {
395
- ({moduleContent, moduleSourceMap} =
396
- await this.getSourceMapForModule({
397
- moduleName,
398
- moduleContent,
399
- resourcePath: resource.getPath()
400
- }));
401
- }
395
+ const outW = this.outW;
402
396
 
403
- const rewriteRes = await rewriteDefine({
404
- moduleName, moduleContent, moduleSourceMap
405
- });
406
- if (rewriteRes) {
407
- const {moduleContent, moduleSourceMap} = rewriteRes;
408
- outW.startSegment(moduleName);
409
- outW.ensureNewLine();
410
- if (moduleSourceMap) {
411
- this.addSourceMap(moduleName, moduleSourceMap);
412
- }
413
- outW.write(moduleContent);
414
- outW.ensureNewLine();
415
- const compressedSize = outW.endSegment();
416
- log.verbose(
417
- ` ${moduleName} (${resource.info != null ? resource.info.size : -1},${compressedSize})`);
418
- } else {
419
- // keep unprocessed modules
420
- remaining.push(moduleName);
397
+ const remaining = [];
398
+ for ( const moduleName of sequence ) {
399
+ if ( /\.js$/.test(moduleName) ) {
400
+ const resource = await this.pool.findResourceWithInfo(moduleName);
401
+
402
+ if (resource.info?.requiresTopLevelScope && !this.allowStringBundling) {
403
+ this.logStringBundlingError(moduleName);
404
+ continue;
405
+ }
406
+
407
+ let moduleContent = (await resource.buffer()).toString();
408
+ moduleContent = removeHashbang(moduleContent);
409
+ let moduleSourceMap;
410
+ if (this.options.sourceMap) {
411
+ ({moduleContent, moduleSourceMap} =
412
+ await this.getSourceMapForModule({
413
+ moduleName,
414
+ moduleContent,
415
+ resourcePath: resource.getPath()
416
+ }));
417
+ }
418
+
419
+ const rewriteRes = await rewriteDefine({
420
+ moduleName, moduleContent, moduleSourceMap
421
+ });
422
+ if (rewriteRes) {
423
+ const {moduleContent, moduleSourceMap} = rewriteRes;
424
+ outW.startSegment(moduleName);
425
+ outW.ensureNewLine();
426
+ if (moduleSourceMap) {
427
+ this.addSourceMap(moduleName, moduleSourceMap);
421
428
  }
429
+ outW.write(moduleContent);
430
+ outW.ensureNewLine();
431
+ const compressedSize = outW.endSegment();
432
+ log.verbose(
433
+ ` ${moduleName} (${resource.info != null ? resource.info.size : -1},${compressedSize})`);
422
434
  } else {
423
435
  // keep unprocessed modules
424
436
  remaining.push(moduleName);
425
437
  }
438
+ } else {
439
+ // keep unprocessed modules
440
+ remaining.push(moduleName);
426
441
  }
427
-
428
- Array.prototype.splice.apply(sequence, [0, sequence.length].concat(remaining));
429
442
  }
430
- }
431
443
 
432
- afterWriteFunctionPreloadSection() {
433
- }
434
-
435
- beforeWritePreloadModule(module, info, resource) {
444
+ Array.prototype.splice.apply(sequence, [0, sequence.length].concat(remaining));
436
445
  }
437
446
 
438
447
  /**
@@ -474,8 +483,8 @@ class BundleBuilder {
474
483
  if (this.options.sourceMap) {
475
484
  // We are actually not interested in the source map this module might contain,
476
485
  // but we should make sure to remove any "sourceMappingURL" from the module content before
477
- // writing it to the bundle. Otherwise browser dev-tools might create unnecessary (and likely incorrect)
478
- // requests for any referenced .map files
486
+ // writing it to the bundle. Otherwise browser dev-tools might create unnecessary
487
+ // (and likely incorrect) requests for any referenced .map files
479
488
  ({moduleContent} =
480
489
  await this.getSourceMapForModule({
481
490
  moduleName,
@@ -538,15 +547,43 @@ class BundleBuilder {
538
547
  });
539
548
  }
540
549
 
541
- writeBundleInfos(sections) {
550
+ logStringBundlingError(moduleName) {
551
+ log.error(
552
+ "Module " + moduleName + " requires top level scope and can only be embedded as a string " +
553
+ "(requires 'eval'), which is not supported with specVersion 4.0 and higher. " +
554
+ "For more information, see the UI5 Tooling documentation " +
555
+ "https://sap.github.io/ui5-tooling/stable/pages/Builder/#javascript-files-requiring-top-level-scope");
556
+ }
557
+
558
+ async checkForStringBundling(moduleName) {
559
+ if (!this.allowStringBundling && /\.js$/.test(moduleName)) {
560
+ const resource = await this.pool.findResourceWithInfo(moduleName);
561
+ if (resource.info?.requiresTopLevelScope) {
562
+ this.logStringBundlingError(moduleName);
563
+ return null;
564
+ }
565
+ }
566
+ return moduleName;
567
+ }
568
+
569
+ async writeBundleInfos(sections) {
542
570
  this.outW.ensureNewLine();
543
571
 
544
572
  let bundleInfoStr = "";
545
573
  if ( sections.length > 0 ) {
546
- bundleInfoStr = this.targetBundleFormat.beforeBundleInfo();
547
- sections.forEach((section, idx) => {
548
- if ( idx > 0 ) {
574
+ bundleInfoStr = "sap.ui.loader.config({bundlesUI5:{\n";
575
+ let initial = true;
576
+ for (let idx = 0; idx < sections.length; idx++) {
577
+ const section = sections[idx];
578
+
579
+ // Remove modules requiring string bundling
580
+ let modules = await Promise.all(section.modules.map(this.checkForStringBundling.bind(this)));
581
+ modules = modules.filter(($) => $) || [];
582
+
583
+ if (!initial) {
549
584
  bundleInfoStr += ",\n";
585
+ } else {
586
+ initial = false;
550
587
  }
551
588
 
552
589
  if (!section.name) {
@@ -557,20 +594,26 @@ class BundleBuilder {
557
594
  `The info might not work as expected. ` +
558
595
  `The name must match the bundle filename (incl. extension such as '.js')`);
559
596
  }
560
- bundleInfoStr += `"${section.name}":[${section.modules.map(makeStringLiteral).join(",")}]`;
561
- });
562
- bundleInfoStr += "\n";
563
- bundleInfoStr += this.targetBundleFormat.afterBundleInfo();
597
+ bundleInfoStr += `"${section.name}":[${modules.map(makeStringLiteral).join(",")}]`;
598
+ }
599
+ bundleInfoStr += "\n}});\n";
564
600
 
565
601
  this.writeWithSourceMap(bundleInfoStr);
566
602
  }
567
603
  }
568
604
 
569
605
  writeRequires(section) {
606
+ if (section.modules.length === 0) {
607
+ return;
608
+ }
570
609
  this.outW.ensureNewLine();
571
- section.modules.forEach( (module) => {
572
- this.writeWithSourceMap(this.targetBundleFormat.requireSync(module));
573
- });
610
+ if (section.async === false) {
611
+ section.modules.forEach( (module) => {
612
+ this.writeWithSourceMap(this.generateRequireSync(module));
613
+ });
614
+ } else {
615
+ this.writeWithSourceMap(this.generateRequire(section.modules));
616
+ }
574
617
  }
575
618
 
576
619
  // When AutoSplit is enabled for depCache, we need to ensure that modules
@@ -579,7 +622,6 @@ class BundleBuilder {
579
622
  // module in the next file. This will also duplicate its dependency definition if we do not filter.
580
623
  #depCacheSet = new Set();
581
624
  async writeDepCache(section) {
582
- const outW = this.outW;
583
625
  let hasDepCache = false;
584
626
 
585
627
  const sequence = section.modules.slice().sort();
@@ -607,11 +649,11 @@ class BundleBuilder {
607
649
  if (deps.length > 0) {
608
650
  if (!hasDepCache) {
609
651
  hasDepCache = true;
610
- outW.ensureNewLine();
611
- this.targetBundleFormat.beforeDepCache(outW, section);
652
+ this.outW.ensureNewLine();
653
+ this.outW.writeln(`sap.ui.loader.config({depCacheUI5:{`);
612
654
  }
613
655
 
614
- outW.writeln(
656
+ this.outW.writeln(
615
657
  `"${module}": [${deps.map((dep) => `"${dep}"`).join(",")}],`
616
658
  );
617
659
  } else {
@@ -621,7 +663,7 @@ class BundleBuilder {
621
663
  }
622
664
 
623
665
  if (hasDepCache) {
624
- this.targetBundleFormat.afterDepCache(outW, section);
666
+ this.outW.writeln(`}});`);
625
667
  }
626
668
  }
627
669
  }
@@ -13,10 +13,11 @@ class ResolvedBundleDefinition {
13
13
  );
14
14
  }
15
15
 
16
- get containsCore() {
16
+ get containsCoreSync() {
17
17
  return this.sections.some(
18
18
  (section) =>
19
- (section.mode === SectionType.Raw || section.mode === SectionType.Require) &&
19
+ (section.mode === SectionType.Raw ||
20
+ (section.mode === SectionType.Require && section.async === false)) &&
20
21
  section.modules.some((module) => module === MODULE__SAP_UI_CORE_CORE)
21
22
  );
22
23
  }
@@ -37,7 +38,7 @@ class ResolvedBundleDefinition {
37
38
  );
38
39
  }
39
40
 
40
- createModuleInfo(pool) {
41
+ createModuleInfo(pool, allowStringBundling) {
41
42
  const bundleInfo = new ModuleInfo();
42
43
  bundleInfo.name = this.name;
43
44
 
@@ -65,7 +66,9 @@ class ResolvedBundleDefinition {
65
66
  modules.map( (submodule) => {
66
67
  return pool.getModuleInfo(submodule).then(
67
68
  (subinfo) => {
68
- if (!bundleInfo.subModules.includes(subinfo.name)) {
69
+ if (!bundleInfo.subModules.includes(subinfo.name) &&
70
+ (!subinfo.requiresTopLevelScope ||
71
+ (subinfo.requiresTopLevelScope && allowStringBundling))) {
69
72
  bundleInfo.addSubModule(subinfo);
70
73
  }
71
74
  }
@@ -77,19 +80,6 @@ class ResolvedBundleDefinition {
77
80
 
78
81
  return promise.then( () => bundleInfo );
79
82
  }
80
-
81
- /*
82
- public JSModuleDefinition getDefinition() {
83
- return moduleDefinition;
84
- }
85
-
86
- public Configuration getConfiguration() {
87
- return moduleDefinition.getConfiguration();
88
- }
89
-
90
-
91
- }
92
- */
93
83
  }
94
84
 
95
85
  class ResolvedSection {
@@ -109,6 +99,10 @@ class ResolvedSection {
109
99
  get declareRawModules() {
110
100
  return this.sectionDefinition.declareRawModules;
111
101
  }
102
+
103
+ get async() {
104
+ return this.sectionDefinition.async;
105
+ }
112
106
  }
113
107
 
114
108
  export default ResolvedBundleDefinition;