@ui5/builder 3.1.0 → 3.2.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.
- package/CHANGELOG.md +22 -1
- package/lib/lbt/bundle/AutoSplitter.js +53 -0
- package/lib/lbt/bundle/Builder.js +63 -0
- package/lib/lbt/bundle/BundleDefinition.js +8 -1
- package/lib/lbt/bundle/ResolvedBundleDefinition.js +5 -1
- package/lib/lbt/bundle/Resolver.js +2 -2
- package/lib/lbt/resources/ResourceFilterList.js +1 -1
- package/lib/lbt/resources/ResourcePool.js +10 -0
- package/lib/processors/jsdoc/lib/createIndexFiles.cjs +18 -6
- package/lib/processors/jsdoc/lib/transformApiJson.cjs +5 -2
- package/lib/processors/jsdoc/lib/ui5/plugin.cjs +4 -4
- package/lib/processors/jsdoc/lib/ui5/template/publish.cjs +14 -4
- package/lib/processors/manifestCreator.js +8 -2
- package/lib/processors/minifier.js +23 -5
- package/lib/tasks/buildThemes.js +23 -5
- package/lib/tasks/bundlers/generateLibraryPreload.js +5 -3
- package/package.json +11 -11
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,26 @@
|
|
|
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
|
+
A list of unreleased changes can be found [here](https://github.com/SAP/ui5-builder/compare/v3.2.0...HEAD).
|
|
6
|
+
|
|
7
|
+
<a name="v3.2.0"></a>
|
|
8
|
+
## [v3.2.0] - 2023-12-12
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
- Incomplete multi-character sanitization ([#959](https://github.com/SAP/ui5-builder/issues/959)) [`d61f1b7`](https://github.com/SAP/ui5-builder/commit/d61f1b744495f5428db33467218077e7996f1575)
|
|
11
|
+
- Add guard against prototype pollution ([#960](https://github.com/SAP/ui5-builder/issues/960)) [`ba230d9`](https://github.com/SAP/ui5-builder/commit/ba230d922cac0acd291dfe18b0ae7a95eae8b190)
|
|
12
|
+
- Incomplete string escaping or encoding ([#958](https://github.com/SAP/ui5-builder/issues/958)) [`50bb0d9`](https://github.com/SAP/ui5-builder/commit/50bb0d97e76fb312412cf29fae18b76cc88df6f4)
|
|
13
|
+
- **manifestCreator:** set fallbackLocale to empty string if no locale is present ([#962](https://github.com/SAP/ui5-builder/issues/962)) [`26526a0`](https://github.com/SAP/ui5-builder/commit/26526a08ff38ee11ed3bd506f7ef0610f1d1ccb0)
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
- depCache bundling mode ([#951](https://github.com/SAP/ui5-builder/issues/951)) [`f2cf564`](https://github.com/SAP/ui5-builder/commit/f2cf564f0f71d635e58a743c7bdef1f427e341b2)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
<a name="v3.1.1"></a>
|
|
20
|
+
## [v3.1.1] - 2023-11-20
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
- Handle graceful termination of workerpool for parallel builds ([#953](https://github.com/SAP/ui5-builder/issues/953)) [`f7b9f27`](https://github.com/SAP/ui5-builder/commit/f7b9f27ac5966bd89e52e4c2d5b03482a0f3dbb7)
|
|
23
|
+
- **Bundling:** Detect manifest.json dependency of libraries [`6f9995f`](https://github.com/SAP/ui5-builder/commit/6f9995f5b47a6094fa93b5d433be849b1d3cdc7e)
|
|
24
|
+
|
|
6
25
|
|
|
7
26
|
<a name="v3.1.0"></a>
|
|
8
27
|
## [v3.1.0] - 2023-10-11
|
|
@@ -832,6 +851,8 @@ to load the custom bundle file instead.
|
|
|
832
851
|
|
|
833
852
|
### Features
|
|
834
853
|
- Add ability to configure component preloads and custom bundles [`2241e5f`](https://github.com/SAP/ui5-builder/commit/2241e5ff98fd95f1f80cc74959655ae7a9c660e7)
|
|
854
|
+
[v3.2.0]: https://github.com/SAP/ui5-builder/compare/v3.1.1...v3.2.0
|
|
855
|
+
[v3.1.1]: https://github.com/SAP/ui5-builder/compare/v3.1.0...v3.1.1
|
|
835
856
|
[v3.1.0]: https://github.com/SAP/ui5-builder/compare/v3.0.9...v3.1.0
|
|
836
857
|
[v3.0.9]: https://github.com/SAP/ui5-builder/compare/v3.0.8...v3.0.9
|
|
837
858
|
[v3.0.8]: https://github.com/SAP/ui5-builder/compare/v3.0.7...v3.0.8
|
|
@@ -41,6 +41,8 @@ class AutoSplitter {
|
|
|
41
41
|
const numberOfParts = options.numberOfParts;
|
|
42
42
|
let totalSize = 0;
|
|
43
43
|
const moduleSizes = Object.create(null);
|
|
44
|
+
const depCacheSizes = [];
|
|
45
|
+
let depCacheLoaderSize = 0;
|
|
44
46
|
this.optimize = !!options.optimize;
|
|
45
47
|
|
|
46
48
|
// ---- resolve module definition
|
|
@@ -74,6 +76,27 @@ class AutoSplitter {
|
|
|
74
76
|
totalSize += "sap.ui.requireSync('');".length + toRequireJSName(module).length;
|
|
75
77
|
});
|
|
76
78
|
break;
|
|
79
|
+
case SectionType.DepCache:
|
|
80
|
+
depCacheLoaderSize = "sap.ui.loader.config({depCacheUI5:{}});".length;
|
|
81
|
+
totalSize += depCacheLoaderSize;
|
|
82
|
+
|
|
83
|
+
section.modules.forEach( (module) => {
|
|
84
|
+
promises.push((async () => {
|
|
85
|
+
const resource = await this.pool.findResourceWithInfo(module);
|
|
86
|
+
const deps = resource.info.dependencies.filter(
|
|
87
|
+
(dep) =>
|
|
88
|
+
!resource.info.isConditionalDependency(dep) &&
|
|
89
|
+
!resource.info.isImplicitDependency(dep)
|
|
90
|
+
);
|
|
91
|
+
if (deps.length > 0) {
|
|
92
|
+
const depSize = `"${module}": [${deps.map((dep) => `"${dep}"`).join(",")}],`.length;
|
|
93
|
+
totalSize += depSize;
|
|
94
|
+
|
|
95
|
+
depCacheSizes.push({size: depSize, module});
|
|
96
|
+
}
|
|
97
|
+
})());
|
|
98
|
+
});
|
|
99
|
+
break;
|
|
77
100
|
default:
|
|
78
101
|
break;
|
|
79
102
|
}
|
|
@@ -180,6 +203,36 @@ class AutoSplitter {
|
|
|
180
203
|
totalSize += 21 + toRequireJSName(module).length;
|
|
181
204
|
});
|
|
182
205
|
break;
|
|
206
|
+
case SectionType.DepCache:
|
|
207
|
+
currentSection = {
|
|
208
|
+
mode: SectionType.DepCache,
|
|
209
|
+
filters: []
|
|
210
|
+
};
|
|
211
|
+
currentModule.sections.push( currentSection );
|
|
212
|
+
totalSize += depCacheLoaderSize;
|
|
213
|
+
|
|
214
|
+
depCacheSizes.forEach((depCache) => {
|
|
215
|
+
if ( part + 1 < numberOfParts && totalSize + depCache.size / 2 > partSize ) {
|
|
216
|
+
part++;
|
|
217
|
+
// start a new module
|
|
218
|
+
totalSize = depCacheLoaderSize;
|
|
219
|
+
currentSection = {
|
|
220
|
+
mode: SectionType.DepCache,
|
|
221
|
+
filters: []
|
|
222
|
+
};
|
|
223
|
+
currentModule = {
|
|
224
|
+
name: moduleNameWithPart.replace(/__part__/, part),
|
|
225
|
+
sections: [currentSection]
|
|
226
|
+
};
|
|
227
|
+
splittedModules.push(currentModule);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (!currentSection.filters.includes(depCache.module)) {
|
|
231
|
+
currentSection.filters.push(depCache.module);
|
|
232
|
+
totalSize += depCache.size;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
break;
|
|
183
236
|
default:
|
|
184
237
|
break;
|
|
185
238
|
}
|
|
@@ -71,6 +71,14 @@ const EVOBundleFormat = {
|
|
|
71
71
|
resolvedModule.executes(MODULE__UI5LOADER_AUTOCONFIG) ||
|
|
72
72
|
resolvedModule.executes(MODULE__JQUERY_SAP_GLOBAL) ||
|
|
73
73
|
resolvedModule.executes(MODULE__SAP_UI_CORE_CORE);
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
beforeDepCache(outW) {
|
|
77
|
+
outW.writeln(`sap.ui.loader.config({depCacheUI5:{`);
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
afterDepCache(outW) {
|
|
81
|
+
outW.writeln(`}});`);
|
|
74
82
|
}
|
|
75
83
|
};
|
|
76
84
|
|
|
@@ -220,6 +228,8 @@ class BundleBuilder {
|
|
|
220
228
|
return this.writeBundleInfos([section]);
|
|
221
229
|
case SectionType.Require:
|
|
222
230
|
return this.writeRequires(section);
|
|
231
|
+
case SectionType.DepCache:
|
|
232
|
+
return this.writeDepCache(section);
|
|
223
233
|
default:
|
|
224
234
|
throw new Error("unknown section mode " + section.mode);
|
|
225
235
|
}
|
|
@@ -549,6 +559,59 @@ class BundleBuilder {
|
|
|
549
559
|
});
|
|
550
560
|
}
|
|
551
561
|
|
|
562
|
+
// When AutoSplit is enabled for depCache, we need to ensure that modules
|
|
563
|
+
// are not duplicated across files. This might happen due to the filters provided.
|
|
564
|
+
// So, certain modules that are included in depCache could be dependencies of another
|
|
565
|
+
// module in the next file. This will also duplicate its dependency definition if we do not filter.
|
|
566
|
+
#depCacheSet = new Set();
|
|
567
|
+
async writeDepCache(section) {
|
|
568
|
+
const outW = this.outW;
|
|
569
|
+
let hasDepCache = false;
|
|
570
|
+
|
|
571
|
+
const sequence = section.modules.slice().sort();
|
|
572
|
+
|
|
573
|
+
if (sequence.length > 0) {
|
|
574
|
+
for (const module of sequence) {
|
|
575
|
+
if (this.#depCacheSet.has(module)) {
|
|
576
|
+
continue;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
this.#depCacheSet.add(module);
|
|
580
|
+
let resource = null;
|
|
581
|
+
try {
|
|
582
|
+
resource = await this.pool.findResourceWithInfo(module);
|
|
583
|
+
} catch (e) {
|
|
584
|
+
log.error(` couldn't find ${module}`);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
if (resource != null) {
|
|
588
|
+
const deps = resource.info.dependencies.filter(
|
|
589
|
+
(dep) =>
|
|
590
|
+
!resource.info.isConditionalDependency(dep) &&
|
|
591
|
+
!resource.info.isImplicitDependency(dep)
|
|
592
|
+
);
|
|
593
|
+
if (deps.length > 0) {
|
|
594
|
+
if (!hasDepCache) {
|
|
595
|
+
hasDepCache = true;
|
|
596
|
+
outW.ensureNewLine();
|
|
597
|
+
this.targetBundleFormat.beforeDepCache(outW, section);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
outW.writeln(
|
|
601
|
+
`"${module}": [${deps.map((dep) => `"${dep}"`).join(",")}],`
|
|
602
|
+
);
|
|
603
|
+
} else {
|
|
604
|
+
log.verbose(` skipped ${module}, no dependencies`);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
if (hasDepCache) {
|
|
610
|
+
this.targetBundleFormat.afterDepCache(outW, section);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
552
615
|
async getSourceMapForModule({moduleName, moduleContent, resourcePath}) {
|
|
553
616
|
let moduleSourceMap = null;
|
|
554
617
|
let newModuleContent = moduleContent;
|
|
@@ -27,5 +27,12 @@ export const SectionType = {
|
|
|
27
27
|
* Usually used as the last section in a merged module to enforce loading and
|
|
28
28
|
* execution of some specific module or modules.
|
|
29
29
|
*/
|
|
30
|
-
Require: "require"
|
|
30
|
+
Require: "require",
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Dependency cache information that lists modules and their dependencies
|
|
34
|
+
* of all types: JS, declarative views/fragments.
|
|
35
|
+
* Only the dependencies of the modules are stored as 'depCache' configuration.
|
|
36
|
+
*/
|
|
37
|
+
DepCache: "depCache"
|
|
31
38
|
};
|
|
@@ -64,7 +64,11 @@ class ResolvedBundleDefinition {
|
|
|
64
64
|
return Promise.all(
|
|
65
65
|
modules.map( (submodule) => {
|
|
66
66
|
return pool.getModuleInfo(submodule).then(
|
|
67
|
-
(subinfo) =>
|
|
67
|
+
(subinfo) => {
|
|
68
|
+
if (!bundleInfo.subModules.includes(subinfo.name)) {
|
|
69
|
+
bundleInfo.addSubModule(subinfo);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
68
72
|
);
|
|
69
73
|
})
|
|
70
74
|
);
|
|
@@ -198,7 +198,7 @@ class BundleResolver {
|
|
|
198
198
|
let oldIgnoredResources;
|
|
199
199
|
let oldSelectedResourcesSequence;
|
|
200
200
|
|
|
201
|
-
if (
|
|
201
|
+
if ( [SectionType.Require, SectionType.DepCache].includes(section.mode) ) {
|
|
202
202
|
oldSelectedResources = selectedResources;
|
|
203
203
|
oldIgnoredResources = visitedResources;
|
|
204
204
|
oldSelectedResourcesSequence = selectedResourcesSequence;
|
|
@@ -254,7 +254,7 @@ class BundleResolver {
|
|
|
254
254
|
});
|
|
255
255
|
|
|
256
256
|
return Promise.all(promises).then( function() {
|
|
257
|
-
if (
|
|
257
|
+
if ( [SectionType.Require, SectionType.DepCache].includes(section.mode) ) {
|
|
258
258
|
newKeys = selectedResourcesSequence;
|
|
259
259
|
selectedResources = oldSelectedResources;
|
|
260
260
|
visitedResources = oldIgnoredResources;
|
|
@@ -95,6 +95,16 @@ async function determineDependencyInfo(resource, rawInfo, pool) {
|
|
|
95
95
|
new ComponentAnalyzer(pool).analyze(resource, info),
|
|
96
96
|
new SmartTemplateAnalyzer(pool).analyze(resource, info)
|
|
97
97
|
);
|
|
98
|
+
} else if ( /(?:^|\/)library\.js/.test(resource.name) ) {
|
|
99
|
+
promises.push(
|
|
100
|
+
(async () => {
|
|
101
|
+
const manifestName = resource.name.replace(/library\.js$/, "manifest.json");
|
|
102
|
+
const manifestResource = await pool.findResource(manifestName).catch(() => null);
|
|
103
|
+
if (manifestResource) {
|
|
104
|
+
info.addDependency(manifestName);
|
|
105
|
+
}
|
|
106
|
+
})()
|
|
107
|
+
);
|
|
98
108
|
}
|
|
99
109
|
|
|
100
110
|
await Promise.all(promises);
|
|
@@ -135,10 +135,11 @@ function createIndexFiles(versionInfoFile, unpackedTestresourcesRoot, targetFile
|
|
|
135
135
|
function collectLists(oSymbol) {
|
|
136
136
|
|
|
137
137
|
function addData(oDataType, oEntityObject, sObjectType, sSymbolName) {
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
const sSince = oDataType !== "since" ? oEntityObject[oDataType].since : oEntityObject.since;
|
|
139
|
+
const sText = oDataType !== "since" ? oEntityObject[oDataType].text : oEntityObject.description;
|
|
140
|
+
const oData = {
|
|
140
141
|
control: sSymbolName,
|
|
141
|
-
text:
|
|
142
|
+
text: sText || undefined,
|
|
142
143
|
type: sObjectType,
|
|
143
144
|
"static": !!oEntityObject.static,
|
|
144
145
|
visibility: oEntityObject.visibility
|
|
@@ -173,7 +174,7 @@ function createIndexFiles(versionInfoFile, unpackedTestresourcesRoot, targetFile
|
|
|
173
174
|
addData("deprecated", oSymbol, "class", oSymbol.name);
|
|
174
175
|
}
|
|
175
176
|
|
|
176
|
-
if (oSymbol.experimental) {
|
|
177
|
+
if (oSymbol.experimental && !oSymbol.deprecated) {
|
|
177
178
|
addData("experimental", oSymbol, "class", oSymbol.name);
|
|
178
179
|
}
|
|
179
180
|
|
|
@@ -187,7 +188,7 @@ function createIndexFiles(versionInfoFile, unpackedTestresourcesRoot, targetFile
|
|
|
187
188
|
addData("deprecated", oMethod, "methods", oSymbol.name);
|
|
188
189
|
}
|
|
189
190
|
|
|
190
|
-
if (oMethod.experimental) {
|
|
191
|
+
if (oMethod.experimental && !oSymbol.deprecated) {
|
|
191
192
|
addData("experimental", oMethod, "methods", oSymbol.name);
|
|
192
193
|
}
|
|
193
194
|
|
|
@@ -202,7 +203,7 @@ function createIndexFiles(versionInfoFile, unpackedTestresourcesRoot, targetFile
|
|
|
202
203
|
addData("deprecated", oEvent, "events", oSymbol.name);
|
|
203
204
|
}
|
|
204
205
|
|
|
205
|
-
if (oEvent.experimental) {
|
|
206
|
+
if (oEvent.experimental && !oSymbol.deprecated) {
|
|
206
207
|
addData("experimental", oEvent, "events", oSymbol.name);
|
|
207
208
|
}
|
|
208
209
|
|
|
@@ -469,6 +470,17 @@ function createIndexFiles(versionInfoFile, unpackedTestresourcesRoot, targetFile
|
|
|
469
470
|
|
|
470
471
|
aKeys.forEach((sKey) => {
|
|
471
472
|
oSorted[sKey] = oList[sKey];
|
|
473
|
+
oSorted[sKey].apis.sort((a,b) => {
|
|
474
|
+
const keyA = `${a.control}|${a.entityName || ""}`.toLowerCase();
|
|
475
|
+
const keyB = `${b.control}|${b.entityName || ""}`.toLowerCase();
|
|
476
|
+
if ( keyA === keyB ) {
|
|
477
|
+
if ( a.static === b.static ) {
|
|
478
|
+
return 0;
|
|
479
|
+
}
|
|
480
|
+
return a.static ? -1 : 1;
|
|
481
|
+
}
|
|
482
|
+
return keyA < keyB ? -1 : 1;
|
|
483
|
+
}); // sort entries within the same version alphabetically (case insensitive)
|
|
472
484
|
});
|
|
473
485
|
|
|
474
486
|
return oSorted;
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
/* eslint-disable */
|
|
9
|
+
|
|
8
10
|
"use strict";
|
|
9
11
|
const cheerio = require("cheerio");
|
|
10
12
|
const path = require('path');
|
|
@@ -462,8 +464,9 @@ function transformer(sInputFile, sOutputFile, sLibraryFile, vDependencyAPIFiles,
|
|
|
462
464
|
|
|
463
465
|
// Description
|
|
464
466
|
if (oAggregation.deprecated) {
|
|
465
|
-
oAggregation.description = formatters.formatDescription(oAggregation.description
|
|
466
|
-
|
|
467
|
+
oAggregation.description = formatters.formatDescription(oAggregation.description);
|
|
468
|
+
oAggregation.deprecatedText = formatters.formatDeprecated(oAggregation.deprecated.since,
|
|
469
|
+
oAggregation.deprecated.text);
|
|
467
470
|
} else {
|
|
468
471
|
oAggregation.description = formatters.formatDescriptionSince(oAggregation.description, oAggregation.since);
|
|
469
472
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* experimental
|
|
22
22
|
*
|
|
23
23
|
* final
|
|
24
|
-
*
|
|
24
|
+
*
|
|
25
25
|
* hideconstructor
|
|
26
26
|
*
|
|
27
27
|
* interface
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
*
|
|
33
33
|
* ui5-restricted
|
|
34
34
|
*
|
|
35
|
-
*
|
|
35
|
+
*
|
|
36
36
|
*
|
|
37
37
|
* It furthermore listens to the following JSDoc3 events to implement additional functionality
|
|
38
38
|
*
|
|
@@ -2137,7 +2137,7 @@ function createAutoDoc(oClassInfo, classComment, doclet, node, parser, filename,
|
|
|
2137
2137
|
"",
|
|
2138
2138
|
newStyle && info.doc ? info.doc : "",
|
|
2139
2139
|
"",
|
|
2140
|
-
|
|
2140
|
+
`@returns {${info.cardinality === "0..n" ? "sap.ui.core.ID[]" : "sap.ui.core.ID|null"}}`,
|
|
2141
2141
|
info.since ? "@since " + info.since : "",
|
|
2142
2142
|
info.deprecation ? "@deprecated " + info.deprecation : "",
|
|
2143
2143
|
info.experimental ? "@experimental " + info.experimental : "",
|
|
@@ -2923,7 +2923,7 @@ exports.handlers = {
|
|
|
2923
2923
|
};
|
|
2924
2924
|
}
|
|
2925
2925
|
|
|
2926
|
-
if ( doclet.kind === 'member' && doclet.isEnum && Array.isArray(doclet.properties) ) {
|
|
2926
|
+
if ( (doclet.kind === 'member' || doclet.kind === 'constant') && doclet.isEnum && Array.isArray(doclet.properties) ) {
|
|
2927
2927
|
// determine unique enum identifier from key set
|
|
2928
2928
|
let enumID = doclet.properties.map(function(prop) {
|
|
2929
2929
|
return prop.name;
|
|
@@ -89,6 +89,10 @@ function merge(target, source) {
|
|
|
89
89
|
if ( source != null ) {
|
|
90
90
|
// simple single source merge
|
|
91
91
|
Object.keys(source).forEach((prop) => {
|
|
92
|
+
// guarding against prototype pollution. (https://codeql.github.com/codeql-query-help/javascript/js-prototype-pollution-utility/#example)
|
|
93
|
+
if (prop === "__proto__" || prop === "constructor") {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
92
96
|
const value = source[prop];
|
|
93
97
|
if ( value != null && value.constructor === Object ) {
|
|
94
98
|
merge(target[prop] || {}, value);
|
|
@@ -169,7 +173,7 @@ function isModuleExport($) {
|
|
|
169
173
|
}
|
|
170
174
|
|
|
171
175
|
function isaClass($) {
|
|
172
|
-
return /^(namespace|interface|class|typedef)$/.test($.kind) || ($.kind === 'member' && $.isEnum )/* isNonEmptyNamespace($) */;
|
|
176
|
+
return /^(namespace|interface|class|typedef)$/.test($.kind) || (($.kind === 'member' || $.kind === 'constant') && $.isEnum )/* isNonEmptyNamespace($) */;
|
|
173
177
|
}
|
|
174
178
|
|
|
175
179
|
function supportsInheritance($) {
|
|
@@ -187,7 +191,7 @@ function supportsInheritance($) {
|
|
|
187
191
|
function isFirstClassSymbol($) {
|
|
188
192
|
return (
|
|
189
193
|
/^(namespace|interface|class|typedef)$/.test($.kind)
|
|
190
|
-
|| $.kind === 'member' && $.isEnum
|
|
194
|
+
|| ($.kind === 'member' || $.kind === 'constant') && $.isEnum
|
|
191
195
|
|| ['function', 'member'].includes($.kind) && isModuleExport($)
|
|
192
196
|
)/* isNonEmptyNamespace($) */;
|
|
193
197
|
}
|
|
@@ -723,7 +727,7 @@ function getMembersOfKind(data, kind) {
|
|
|
723
727
|
switch (kind) {
|
|
724
728
|
case 'property':
|
|
725
729
|
fnFilter = function($) {
|
|
726
|
-
return $.kind === 'constant' ||
|
|
730
|
+
return ($.kind === 'constant' || $.kind === 'member') && !$.isEnum;
|
|
727
731
|
};
|
|
728
732
|
break;
|
|
729
733
|
case 'event':
|
|
@@ -2030,7 +2034,7 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
|
|
|
2030
2034
|
}
|
|
2031
2035
|
*/
|
|
2032
2036
|
|
|
2033
|
-
const kind = (symbol.kind === 'member' && symbol.isEnum) ? "enum" : symbol.kind; // handle pseudo-kind 'enum'
|
|
2037
|
+
const kind = ((symbol.kind === 'member' || symbol.kind === 'constant') && symbol.isEnum) ? "enum" : symbol.kind; // handle pseudo-kind 'enum'
|
|
2034
2038
|
|
|
2035
2039
|
tag(kind);
|
|
2036
2040
|
|
|
@@ -2118,7 +2122,13 @@ function createAPIJSON4Symbol(symbol, omitDefaults) {
|
|
|
2118
2122
|
// secTags(symbol); // TODO repeat from class?
|
|
2119
2123
|
closeTag("constructor");
|
|
2120
2124
|
|
|
2125
|
+
} else {
|
|
2126
|
+
|
|
2127
|
+
// even though the constructor is omitted here, the "hide" information is needed because in TypeScript it even exists when omitted
|
|
2128
|
+
attrib("hideconstructor", true, /* default */ false, /* raw */ true); // as boolean
|
|
2129
|
+
|
|
2121
2130
|
}
|
|
2131
|
+
|
|
2122
2132
|
} else if ( kind === 'namespace' ) {
|
|
2123
2133
|
if ( symbol.__ui5.stereotype || symbol.__ui5.metadata ) {
|
|
2124
2134
|
tag("ui5-metadata");
|
|
@@ -233,7 +233,11 @@ async function createManifest(
|
|
|
233
233
|
if ( library.getDocumentation() ) {
|
|
234
234
|
let desc = library.getDocumentation();
|
|
235
235
|
// remove all tags
|
|
236
|
-
|
|
236
|
+
let prevDesc;
|
|
237
|
+
do { // Safely strip tags (https://codeql.github.com/codeql-query-help/javascript/js-incomplete-multi-character-sanitization/#example)
|
|
238
|
+
prevDesc = desc;
|
|
239
|
+
desc = desc.replace(/\s+/g, " ").replace(/<\/?[a-zA-Z][a-zA-Z0-9_$.]*(\s[^>]*)>/g, "");
|
|
240
|
+
} while (prevDesc !== desc);
|
|
237
241
|
// extract summary (first sentence)
|
|
238
242
|
const m = /^([\w\W]+?[.;!?])[^a-zA-Z0-9_$]/.exec(desc);
|
|
239
243
|
return m ? m[1] : desc;
|
|
@@ -556,9 +560,11 @@ async function createManifest(
|
|
|
556
560
|
|
|
557
561
|
const supportedLocalesArray = Array.from(supportedLocales);
|
|
558
562
|
supportedLocalesArray.sort();
|
|
563
|
+
|
|
559
564
|
return {
|
|
560
565
|
bundleUrl: i18n,
|
|
561
|
-
supportedLocales: supportedLocalesArray
|
|
566
|
+
supportedLocales: supportedLocalesArray,
|
|
567
|
+
fallbackLocale: supportedLocalesArray.length === 1 ? supportedLocalesArray[0] : undefined
|
|
562
568
|
};
|
|
563
569
|
}
|
|
564
570
|
|
|
@@ -6,6 +6,7 @@ import workerpool from "workerpool";
|
|
|
6
6
|
import Resource from "@ui5/fs/Resource";
|
|
7
7
|
import {getLogger} from "@ui5/logger";
|
|
8
8
|
const log = getLogger("builder:processors:minifier");
|
|
9
|
+
import {setTimeout as setTimeoutPromise} from "node:timers/promises";
|
|
9
10
|
|
|
10
11
|
const debugFileRegex = /((?:\.view|\.fragment|\.controller|\.designtime|\.support)?\.js)$/;
|
|
11
12
|
|
|
@@ -28,11 +29,28 @@ function getPool(taskUtil) {
|
|
|
28
29
|
workerType: "auto",
|
|
29
30
|
maxWorkers
|
|
30
31
|
});
|
|
31
|
-
taskUtil.registerCleanupTask(() => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
taskUtil.registerCleanupTask((force) => {
|
|
33
|
+
const attemptPoolTermination = async () => {
|
|
34
|
+
log.verbose(`Attempt to terminate the workerpool...`);
|
|
35
|
+
|
|
36
|
+
if (!pool) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// There are many stats that could be used, but these ones seem the most
|
|
41
|
+
// convenient. When all the (available) workers are idle, then it's safe to terminate.
|
|
42
|
+
let {idleWorkers, totalWorkers} = pool.stats();
|
|
43
|
+
while (idleWorkers !== totalWorkers && !force) {
|
|
44
|
+
await setTimeoutPromise(100); // Wait a bit workers to finish and try again
|
|
45
|
+
({idleWorkers, totalWorkers} = pool.stats());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const poolToBeTerminated = pool;
|
|
49
|
+
pool = null;
|
|
50
|
+
return poolToBeTerminated.terminate(force);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return attemptPoolTermination();
|
|
36
54
|
});
|
|
37
55
|
}
|
|
38
56
|
return pool;
|
package/lib/tasks/buildThemes.js
CHANGED
|
@@ -7,6 +7,7 @@ import {fileURLToPath} from "node:url";
|
|
|
7
7
|
import os from "node:os";
|
|
8
8
|
import workerpool from "workerpool";
|
|
9
9
|
import {deserializeResources, serializeResources, FsMainThreadInterface} from "../processors/themeBuilderWorker.js";
|
|
10
|
+
import {setTimeout as setTimeoutPromise} from "node:timers/promises";
|
|
10
11
|
|
|
11
12
|
let pool;
|
|
12
13
|
|
|
@@ -23,11 +24,28 @@ function getPool(taskUtil) {
|
|
|
23
24
|
workerType: "thread",
|
|
24
25
|
maxWorkers
|
|
25
26
|
});
|
|
26
|
-
taskUtil.registerCleanupTask(() => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
taskUtil.registerCleanupTask((force) => {
|
|
28
|
+
const attemptPoolTermination = async () => {
|
|
29
|
+
log.verbose(`Attempt to terminate the workerpool...`);
|
|
30
|
+
|
|
31
|
+
if (!pool) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// There are many stats that could be used, but these ones seem the most
|
|
36
|
+
// convenient. When all the (available) workers are idle, then it's safe to terminate.
|
|
37
|
+
let {idleWorkers, totalWorkers} = pool.stats();
|
|
38
|
+
while (idleWorkers !== totalWorkers && !force) {
|
|
39
|
+
await setTimeoutPromise(100); // Wait a bit workers to finish and try again
|
|
40
|
+
({idleWorkers, totalWorkers} = pool.stats());
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const poolToBeTerminated = pool;
|
|
44
|
+
pool = null;
|
|
45
|
+
return poolToBeTerminated.terminate(force);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
return attemptPoolTermination();
|
|
31
49
|
});
|
|
32
50
|
}
|
|
33
51
|
return pool;
|
|
@@ -32,7 +32,11 @@ function getDefaultLibraryPreloadFilters(namespace, excludes) {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
function getBundleDefinition(namespace, excludes) {
|
|
35
|
-
//
|
|
35
|
+
// Note: This configuration is only used when no bundle definition in ui5.yaml exists (see "skipBundles" parameter)
|
|
36
|
+
|
|
37
|
+
// TODO: Remove this hardcoded bundle definition.
|
|
38
|
+
// sap.ui.core ui5.yaml contains a configuration since UI5 1.103.0 (specVersion 2.4)
|
|
39
|
+
// so this is still required to build UI5 versions <= 1.102.0.
|
|
36
40
|
if (namespace === "sap/ui/core") {
|
|
37
41
|
return {
|
|
38
42
|
name: `${namespace}/library-preload.js`,
|
|
@@ -51,8 +55,6 @@ function getBundleDefinition(namespace, excludes) {
|
|
|
51
55
|
filters: [
|
|
52
56
|
// Note: Don't pass configured preload excludes for sap.ui.core
|
|
53
57
|
// as they are already hardcoded below.
|
|
54
|
-
// In future the sap/ui/core/library-preload should be configured
|
|
55
|
-
// as a custom bundle in the ui5.yaml.
|
|
56
58
|
...getDefaultLibraryPreloadFilters(namespace),
|
|
57
59
|
|
|
58
60
|
`!${namespace}/cldr/`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ui5/builder",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "UI5 Tooling - Builder",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "SAP SE",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"jsdoc-watch": "npm run jsdoc && chokidar \"./lib/**/*.js\" -c \"npm run jsdoc-generate\"",
|
|
48
48
|
"preversion": "npm test",
|
|
49
49
|
"version": "git-chglog --sort semver --next-tag v$npm_package_version -o CHANGELOG.md v3.0.0.. && git add CHANGELOG.md",
|
|
50
|
-
"
|
|
50
|
+
"prepublishOnly": "git push --follow-tags",
|
|
51
51
|
"release-note": "git-chglog --sort semver -c .chglog/release-config.yml v$npm_package_version",
|
|
52
52
|
"depcheck": "depcheck --ignores @ui5/builder,docdash,@istanbuljs/esm-loader-hook,catharsis --parsers='**/*.js:es6,**/*.cjs:es6'"
|
|
53
53
|
},
|
|
@@ -131,31 +131,31 @@
|
|
|
131
131
|
"pretty-data": "^0.40.0",
|
|
132
132
|
"rimraf": "^5.0.5",
|
|
133
133
|
"semver": "^7.5.4",
|
|
134
|
-
"terser": "^5.
|
|
135
|
-
"workerpool": "^6.5.
|
|
134
|
+
"terser": "^5.26.0",
|
|
135
|
+
"workerpool": "^6.5.1",
|
|
136
136
|
"xml2js": "^0.6.2"
|
|
137
137
|
},
|
|
138
138
|
"devDependencies": {
|
|
139
139
|
"@istanbuljs/esm-loader-hook": "^0.2.0",
|
|
140
|
-
"@jridgewell/trace-mapping": "^0.3.
|
|
141
|
-
"@ui5/project": "^3.
|
|
140
|
+
"@jridgewell/trace-mapping": "^0.3.20",
|
|
141
|
+
"@ui5/project": "^3.8.0",
|
|
142
142
|
"ava": "^5.3.1",
|
|
143
143
|
"chai": "^4.3.10",
|
|
144
144
|
"chai-fs": "^2.0.0",
|
|
145
145
|
"chokidar-cli": "^3.0.0",
|
|
146
146
|
"cross-env": "^7.0.3",
|
|
147
|
-
"depcheck": "^1.4.
|
|
147
|
+
"depcheck": "^1.4.7",
|
|
148
148
|
"docdash": "^2.0.2",
|
|
149
|
-
"eslint": "^8.
|
|
149
|
+
"eslint": "^8.55.0",
|
|
150
150
|
"eslint-config-google": "^0.14.0",
|
|
151
151
|
"eslint-plugin-ava": "^14.0.0",
|
|
152
|
-
"eslint-plugin-jsdoc": "^46.
|
|
153
|
-
"esmock": "^2.
|
|
152
|
+
"eslint-plugin-jsdoc": "^46.9.0",
|
|
153
|
+
"esmock": "^2.6.0",
|
|
154
154
|
"line-column": "^1.0.2",
|
|
155
155
|
"nyc": "^15.1.0",
|
|
156
156
|
"open-cli": "^7.2.0",
|
|
157
157
|
"recursive-readdir": "^2.2.3",
|
|
158
|
-
"sinon": "^16.1.
|
|
158
|
+
"sinon": "^16.1.3",
|
|
159
159
|
"tap-xunit": "^2.4.1"
|
|
160
160
|
}
|
|
161
161
|
}
|