Socket
Socket
Sign inDemoInstall

@ui5/builder

Package Overview
Dependencies
122
Maintainers
4
Versions
138
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.0.9 to 3.1.0

18

CHANGELOG.md

@@ -5,6 +5,19 @@ # Changelog

A list of unreleased changes can be found [here](https://github.com/SAP/ui5-builder/compare/v3.0.9...HEAD).
A list of unreleased changes can be found [here](https://github.com/SAP/ui5-builder/compare/v3.1.0...HEAD).
<a name="v3.1.0"></a>
## [v3.1.0] - 2023-10-11
### Bug Fixes
- **bundle/Builder:** Add missing 'names' attribute to generated source maps [`57e0e50`](https://github.com/SAP/ui5-builder/commit/57e0e5047638a9a704a696b8af7780fbbceefbc4)
### Features
- Validate apiVersion property in Library.init ([#943](https://github.com/SAP/ui5-builder/issues/943)) [`52bf258`](https://github.com/SAP/ui5-builder/commit/52bf25842a59c3fa1ddbe71b482b232e18b55288)
- **Minifier:** Support input source maps ([#780](https://github.com/SAP/ui5-builder/issues/780)) [`67ecb27`](https://github.com/SAP/ui5-builder/commit/67ecb27e44a2d84e6b2203f31049220dcbcd41f0)
### Reverts
- [INTERNAL] Azure Pipelines: Switch back to Node 20.5.x
<a name="v3.0.9"></a>
## [v3.0.9] - 2023-07-25
## [v3.0.9] - 2023-07-26

@@ -823,2 +836,3 @@ <a name="v3.0.8"></a>

- Add ability to configure component preloads and custom bundles [`2241e5f`](https://github.com/SAP/ui5-builder/commit/2241e5ff98fd95f1f80cc74959655ae7a9c660e7)
[v3.1.0]: https://github.com/SAP/ui5-builder/compare/v3.0.9...v3.1.0
[v3.0.9]: https://github.com/SAP/ui5-builder/compare/v3.0.8...v3.0.9

@@ -825,0 +839,0 @@ [v3.0.8]: https://github.com/SAP/ui5-builder/compare/v3.0.7...v3.0.8

@@ -64,2 +64,5 @@

// do nothing, for all other supported properties
} else if ( key === "apiVersion" &&
(value.type === Syntax.Literal && typeof value.value === "number") ) {
// just a validation
} else {

@@ -66,0 +69,0 @@ log.error(

14

lib/lbt/bundle/Builder.js

@@ -21,3 +21,3 @@ /* eslint quotes: ["error", "double", { "allowTemplateLiterals": true }] */

const sourceMappingUrlPattern = /\/\/# sourceMappingURL=(.+)\s*$/;
const sourceMappingUrlPattern = /\/\/# sourceMappingURL=(\S+)\s*$/;
const httpPattern = /^https?:\/\//i;

@@ -336,2 +336,4 @@ const xmlHtmlPrePattern = /<(?:\w+:)?pre\b/;

// Reminder on the structure of line-segments in the map:
// [generatedCodeColumn, sourceIndex, sourceCodeLine, sourceCodeColumn, nameIndex]
if (map.mappings.startsWith(";")) {

@@ -342,2 +344,7 @@ // If first line is not already mapped (typical for comments or parentheses), add a mapping to

map.mappings = "AAAA" + map.mappings;
} else if (this.outW.columnOffset === 0 && !map.mappings.startsWith("A")) {
// If first column of the first line is not already mapped, add a mapping for the same reason as above.
// This is typical for transpiled code, where there is a bunch of generated code at the beginning that
// can't be mapped to the original source
map.mappings = "AAAA," + map.mappings;
}

@@ -598,5 +605,3 @@

const sourceMapResource = await this.pool.findResource(sourceMapFileCandidate);
if (sourceMapResource) {
moduleSourceMap = (await sourceMapResource.buffer()).toString();
}
moduleSourceMap = (await sourceMapResource.buffer()).toString();
} catch (e) {

@@ -779,2 +784,3 @@ // No input source map

version: 3,
names: [],
sources: [moduleName],

@@ -781,0 +787,0 @@ // TODO: check whether moduleContent.match() with \n is better w.r.t performance/memory usage

import {fileURLToPath} from "node:url";
import posixPath from "node:path/posix";
import {promisify} from "node:util";
import os from "node:os";

@@ -16,2 +17,5 @@ import workerpool from "workerpool";

const sourceMappingUrlPattern = /\/\/# sourceMappingURL=(\S+)\s*$/;
const httpPattern = /^https?:\/\//i;
// Shared workerpool across all executions until the taskUtil cleanup is triggered

@@ -42,2 +46,59 @@ let pool;

async function extractAndRemoveSourceMappingUrl(resource) {
const resourceContent = await resource.getString();
const resourcePath = resource.getPath();
const sourceMappingUrlMatch = resourceContent.match(sourceMappingUrlPattern);
if (sourceMappingUrlMatch) {
const sourceMappingUrl = sourceMappingUrlMatch[1];
if (log.isLevelEnabled("silly")) {
log.silly(`Found source map reference in content of resource ${resourcePath}: ${sourceMappingUrl}`);
}
// Strip sourceMappingURL from the resource to be minified
// It is not required anymore and will be replaced for in the minified resource
// and its debug variant anyways
resource.setString(resourceContent.replace(sourceMappingUrlPattern, ""));
return sourceMappingUrl;
}
return null;
}
async function getSourceMapFromUrl({sourceMappingUrl, resourcePath, readFile}) {
// =======================================================================
// This code is almost identical to code located in lbt/bundle/Builder.js
// Please try to update both places when making changes
// =======================================================================
if (sourceMappingUrl.startsWith("data:")) {
// Data-URI indicates an inline source map
const expectedTypeAndEncoding = "data:application/json;charset=utf-8;base64,";
if (sourceMappingUrl.startsWith(expectedTypeAndEncoding)) {
const base64Content = sourceMappingUrl.slice(expectedTypeAndEncoding.length);
// Create a resource with a path suggesting it's the source map for the resource
// (which it is but inlined)
return Buffer.from(base64Content, "base64").toString();
} else {
log.warn(
`Source map reference in resource ${resourcePath} is a data URI but has an unexpected` +
`encoding: ${sourceMappingUrl}. Expected it to start with ` +
`"data:application/json;charset=utf-8;base64,"`);
}
} else if (httpPattern.test(sourceMappingUrl)) {
log.warn(`Source map reference in resource ${resourcePath} is an absolute URL. ` +
`Currently, only relative URLs are supported.`);
} else if (posixPath.isAbsolute(sourceMappingUrl)) {
log.warn(`Source map reference in resource ${resourcePath} is an absolute path. ` +
`Currently, only relative paths are supported.`);
} else {
const sourceMapPath = posixPath.join(posixPath.dirname(resourcePath), sourceMappingUrl);
try {
const sourceMapContent = await readFile(sourceMapPath);
return sourceMapContent.toString();
} catch (e) {
// No input source map
log.warn(`Unable to read source map for resource ${resourcePath}: ${e.message}`);
}
}
}
/**

@@ -67,5 +128,12 @@ * @public

* @param {@ui5/fs/Resource[]} parameters.resources List of resources to be processed
* @param {fs|module:@ui5/fs/fsInterface} parameters.fs Node fs or custom
* [fs interface]{@link module:@ui5/fs/fsInterface}. Required when setting "readSourceMappingUrl" to true
* @param {@ui5/builder/tasks/TaskUtil|object} [parameters.taskUtil] TaskUtil instance.
* Required when using the <code>useWorkers</code> option
* @param {object} [parameters.options] Options
* @param {boolean} [parameters.options.readSourceMappingUrl=false]
* Whether to make use of any existing source maps referenced in the resources to be minified. Use this option to
* preserve references to the original source files, such as TypeScript files, in the generated source map.<br>
* If a resource has been modified by a previous task, any existing source map will be ignored regardless of this
* setting. This is to ensure that no inconsistent source maps are used. Check the verbose log for details.
* @param {boolean} [parameters.options.addSourceMappingUrl=true]

@@ -78,4 +146,10 @@ * Whether to add a sourceMappingURL reference to the end of the minified resource

*/
export default async function({resources, taskUtil, options: {addSourceMappingUrl = true, useWorkers = false} = {}}) {
export default async function({
resources, fs, taskUtil, options: {readSourceMappingUrl = false, addSourceMappingUrl = true, useWorkers = false
} = {}}) {
let minify;
if (readSourceMappingUrl && !fs) {
throw new Error(`Option 'readSourceMappingUrl' requires parameter 'fs' to be provided`);
}
if (useWorkers) {

@@ -93,8 +167,7 @@ if (!taskUtil) {

return Promise.all(resources.map(async (resource) => {
const dbgPath = resource.getPath().replace(debugFileRegex, "-dbg$1");
const dbgResource = await resource.clone();
dbgResource.setPath(dbgPath);
const resourcePath = resource.getPath();
const dbgPath = resourcePath.replace(debugFileRegex, "-dbg$1");
const dbgFilename = posixPath.basename(dbgPath);
const filename = posixPath.basename(resource.getPath());
const code = await resource.getString();

@@ -107,4 +180,78 @@ const sourceMapOptions = {

}
const dbgFilename = posixPath.basename(dbgPath);
// Remember contentModified flag before making changes to the resource via setString
const resourceContentModified = resource.getSourceMetadata()?.contentModified;
// In any case: Extract *and remove* source map reference from resource before cloning it
const sourceMappingUrl = await extractAndRemoveSourceMappingUrl(resource);
const code = await resource.getString();
// Create debug variant based off the original resource before minification
const dbgResource = await resource.clone();
dbgResource.setPath(dbgPath);
let dbgSourceMapResource;
if (sourceMappingUrl) {
if (resourceContentModified) {
log.verbose(
`Source map found in resource will be ignored because the resource has been ` +
`modified in a previous task: ${resourcePath}`);
} else if (readSourceMappingUrl) {
// Try to find a source map reference in the to-be-minified resource
// If we find one, provide it to terser as an input source map and keep using it for the
// debug variant of the resource
const sourceMapContent = await getSourceMapFromUrl({
sourceMappingUrl,
resourcePath,
readFile: promisify(fs.readFile)
});
if (sourceMapContent) {
const sourceMapJson = JSON.parse(sourceMapContent);
if (sourceMapJson.sections) {
// TODO 4.0
// Module "@jridgewell/trace-mapping" (used by Terser) can't handle index map sections lacking
// a "names" array. Since this is a common occurrence for UI5 Tooling bundles, we search for
// such cases here and fix them until https://github.com/jridgewell/trace-mapping/pull/29 is
// resolved and Terser upgraded the dependency
// Create a dedicated clone before modifying the source map as to not alter the debug source map
const clonedSourceMapJson = JSON.parse(sourceMapContent);
clonedSourceMapJson.sections.forEach(({map}) => {
if (!map.names) {
// Add missing names array
map.names = [];
}
});
// Use modified source map as input source map
sourceMapOptions.content = JSON.stringify(clonedSourceMapJson);
} else {
// Provide source map to terser as "input source map"
sourceMapOptions.content = sourceMapContent;
}
// Use the original source map for the debug variant of the resource
// First update the file reference within the source map
sourceMapJson.file = dbgFilename;
// Then create a new resource
dbgSourceMapResource = new Resource({
string: JSON.stringify(sourceMapJson),
path: dbgPath + ".map"
});
// And reference the resource in the debug resource
dbgResource.setString(code + `//# sourceMappingURL=${dbgFilename}.map\n`);
}
} else {
// If the original resource content was unmodified and the input source map was not parsed,
// re-add the original source map reference to the debug variant
if (!sourceMappingUrl.startsWith("data:") && !sourceMappingUrl.endsWith(filename + ".map")) {
// Do not re-add inline source maps as well as references to the source map of
// the minified resource
dbgResource.setString(code + `//# sourceMappingURL=${sourceMappingUrl}\n`);
}
}
}
const result = await minify({

@@ -121,4 +268,7 @@ filename,

});
return {resource, dbgResource, sourceMapResource};
return {resource, dbgResource, sourceMapResource, dbgSourceMapResource};
}));
}
export const __localFunctions__ = (process.env.NODE_ENV === "test") ?
{getSourceMapFromUrl} : undefined;

@@ -65,3 +65,5 @@ import workerpool from "workerpool";

`Minification failed with error: ${err.message} in file ${filename} ` +
`(line ${err.line}, col ${err.col}, pos ${err.pos})`);
`(line ${err.line}, col ${err.col}, pos ${err.pos})`, {
cause: err
});
}

@@ -68,0 +70,0 @@ }

@@ -21,4 +21,4 @@ import {getNonDebugName} from "../../../lbt/utils/ModuleName.js";

const resource = resources[i];
if (taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
const resourcePath = resource.getPath();
const resourcePath = resource.getPath();
if (resourcePath.endsWith(".js") && taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
const nonDbgPath = getNonDebugName(resourcePath);

@@ -25,0 +25,0 @@ if (!nonDbgPath) {

import minifier from "../processors/minifier.js";
import fsInterface from "@ui5/fs/fsInterface";

@@ -22,11 +23,18 @@ /**

* be tagged as "OmitFromBuildResult" and no sourceMappingURL shall be added to the minified resource
* @param {boolean} [parameters.options.useInputSourceMaps=true] Whether to make use of any existing source
* maps referenced in the resources to be minified. Use this option to preserve reference to the original
* source files, such as TypeScript files, in the generated source map.
* @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
*/
export default async function({workspace, taskUtil, options: {pattern, omitSourceMapResources = false}}) {
export default async function({
workspace, taskUtil, options: {pattern, omitSourceMapResources = false, useInputSourceMaps = true
}}) {
const resources = await workspace.byGlob(pattern);
const processedResources = await minifier({
resources,
fs: fsInterface(workspace),
taskUtil,
options: {
addSourceMappingUrl: !omitSourceMapResources,
readSourceMappingUrl: !!useInputSourceMaps,
useWorkers: !!taskUtil,

@@ -36,3 +44,5 @@ }

return Promise.all(processedResources.map(async ({resource, dbgResource, sourceMapResource}) => {
return Promise.all(processedResources.map(async ({
resource, dbgResource, sourceMapResource, dbgSourceMapResource
}) => {
if (taskUtil) {

@@ -45,2 +55,8 @@ taskUtil.setTag(resource, taskUtil.STANDARD_TAGS.HasDebugVariant);

}
if (dbgSourceMapResource) {
taskUtil.setTag(dbgSourceMapResource, taskUtil.STANDARD_TAGS.IsDebugVariant);
if (omitSourceMapResources) {
taskUtil.setTag(dbgSourceMapResource, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
}
}
}

@@ -50,5 +66,6 @@ return Promise.all([

workspace.write(dbgResource),
workspace.write(sourceMapResource)
workspace.write(sourceMapResource),
dbgSourceMapResource && workspace.write(dbgSourceMapResource)
]);
}));
}
{
"name": "@ui5/builder",
"version": "3.0.9",
"version": "3.1.0",
"description": "UI5 Tooling - Builder",

@@ -122,3 +122,3 @@ "author": {

"@jridgewell/sourcemap-codec": "^1.4.15",
"@ui5/fs": "^3.0.4",
"@ui5/fs": "^3.0.5",
"@ui5/logger": "^3.0.0",

@@ -133,29 +133,31 @@ "cheerio": "1.0.0-rc.12",

"pretty-data": "^0.40.0",
"rimraf": "^5.0.1",
"rimraf": "^5.0.5",
"semver": "^7.5.4",
"terser": "^5.19.2",
"workerpool": "^6.4.0",
"xml2js": "^0.6.0"
"terser": "^5.21.0",
"workerpool": "^6.5.0",
"xml2js": "^0.6.2"
},
"devDependencies": {
"@istanbuljs/esm-loader-hook": "^0.2.0",
"@ui5/project": "^3.4.2",
"@jridgewell/trace-mapping": "^0.3.19",
"@ui5/project": "^3.7.1",
"ava": "^5.3.1",
"chai": "^4.3.7",
"chai": "^4.3.10",
"chai-fs": "^2.0.0",
"chokidar-cli": "^3.0.0",
"cross-env": "^7.0.3",
"depcheck": "^1.4.3",
"docdash": "^2.0.1",
"eslint": "^8.45.0",
"depcheck": "^1.4.6",
"docdash": "^2.0.2",
"eslint": "^8.51.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-ava": "^14.0.0",
"eslint-plugin-jsdoc": "^46.4.4",
"esmock": "^2.3.2",
"eslint-plugin-jsdoc": "^46.8.2",
"esmock": "^2.5.2",
"line-column": "^1.0.2",
"nyc": "^15.1.0",
"open-cli": "^7.2.0",
"recursive-readdir": "^2.2.3",
"sinon": "^15.2.0",
"sinon": "^16.1.0",
"tap-xunit": "^2.4.1"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc