diff --git a/lib/lbt/bundle/Builder.js b/lib/lbt/bundle/Builder.js index 1e6c4f17f..18aeb8bf2 100644 --- a/lib/lbt/bundle/Builder.js +++ b/lib/lbt/bundle/Builder.js @@ -2,10 +2,10 @@ // for consistency of write calls, we generally allow template literals "use strict"; -const terser = require("terser"); +const path = require("path"); const {pd} = require("pretty-data"); const {parseJS, Syntax} = require("../utils/parseUtils"); -// const MOZ_SourceMap = require("source-map"); +const {encode: encodeMappings, decode: decodeMappings} = require("sourcemap-codec"); const {isMethodCall} = require("../utils/ASTUtils"); const ModuleName = require("../utils/ModuleName"); @@ -18,7 +18,7 @@ const {SectionType} = require("./BundleDefinition"); const BundleWriter = require("./BundleWriter"); const log = require("@ui5/logger").getLogger("lbt:bundle:Builder"); -const copyrightCommentsPattern = /copyright|\(c\)(?:[0-9]+|\s+[0-9A-za-z])|released under|license|\u00a9|^@ui5-bundle-raw-include |^@ui5-bundle /i; +const sourcemapPattern = /\/\/# sourceMappingURL=data:application\/json;charset=utf-8;base64,(.+)/i; const xmlHtmlPrePattern = /<(?:\w+:)?pre\b/; const strReplacements = { @@ -147,6 +147,7 @@ class BundleBuilder { this.options = options || {}; this.optimize = !!this.options.optimize; + this.options.sourceMap = this.options.sourceMap === undefined ? true : this.options.sourceMap; // when decorateBootstrapModule is set to false, we don't write the optimized flag // and don't write the try catch wrapper @@ -156,6 +157,14 @@ class BundleBuilder { // TODO is the following condition ok or should the availability of jquery.sap.global.js be configurable? this.jqglobalAvailable = !resolvedModule.containsGlobal; this.openModule(resolvedModule.name); + + this._sourceMap = { + version: 3, + file: path.posix.basename(resolvedModule.name), + sections: [], + }; + this._bundleName = resolvedModule.name; + let bundleInfos = []; // create all sections in sequence for ( const section of resolvedModule.sections ) { @@ -184,6 +193,7 @@ class BundleBuilder { return { name: module.name, content: this.outW.toString(), + sourceMap: this.options.sourceMap ? JSON.stringify(this._sourceMap) : null, bundleInfo: bundleInfo }; } @@ -213,11 +223,9 @@ class BundleBuilder { this.outW.writeln(`if (oError.name != "Restart") { throw oError; }`); this.outW.writeln(`}`); } - /* NODE-TODO - if ( writeSourceMap && writeSourceMapAnnotation ) { - outW.ensureNewLine(); - outW.write("//# sourceMappingURL=" + moduleName.getBaseName().replaceFirst("\\.js$", ".js.map")); - }*/ + if (this.options.sourceMap) { + this.outW.writeln(`//# sourceMappingURL=${path.basename(resolvedModule.name)}.map`); + } } addSection(section) { @@ -281,12 +289,8 @@ class BundleBuilder { } async writeRawModule(module, resource) { - let fileContent = await resource.buffer(); - if ( /\.js$/.test(module) ) { - fileContent = await this.compressJS( fileContent, resource ); - } this.outW.ensureNewLine(); - this.outW.write( fileContent ); + this.outW.write( (await resource.buffer()).toString() ); } async writePreloadFunction(section) { @@ -330,60 +334,80 @@ class BundleBuilder { // this.afterWriteFunctionPreloadSection(); } - async compressJS(fileContent, resource) { - if ( this.optimize ) { - const result = await terser.minify({ - [resource.name]: String(fileContent) - }, { - compress: false, // TODO configure? - output: { - comments: copyrightCommentsPattern, - wrap_func_args: false - } - // , outFileName: resource.name - // , outSourceMap: true - }); - // console.log(result.map); - // const map = new MOZ_SourceMap.SourceMapConsumer(result.map); - // map.eachMapping(function (m) { console.log(m); }); // console.log(map); - fileContent = result.code; - // throw new Error(); - } - return fileContent; - } - beforeWriteFunctionPreloadSection(sequence) { // simple version: just sort alphabetically sequence.sort(); } + async addSourceMap(map) { + if (!map) { + throw new Error("No source map provided"); + } + this._sourceMap.sections.push({ + offset: { + line: this.outW.lineOffset, + column: this.outW.columnOffset + }, + map + }); + } + async rewriteAMDModules(sequence) { if ( this.options.usePredefineCalls ) { const outW = this.outW; const remaining = []; - for ( const module of sequence ) { - if ( /\.js$/.test(module) ) { - // console.log("Processing " + module); - const resource = await this.pool.findResourceWithInfo(module); - let code = await resource.buffer(); - code = rewriteDefine(this.targetBundleFormat, code, module); - if ( code ) { - outW.startSegment(module); + for ( const moduleName of sequence ) { + if ( /\.js$/.test(moduleName) ) { + // console.log("Processing " + moduleName); + const resource = await this.pool.findResourceWithInfo(moduleName); + let moduleCode = (await resource.buffer()).toString(); + let moduleSourceMap = false; + if (this.options.sourceMap) { + moduleSourceMap = null; + try { + const sourceMapResource = await this.pool.findResource(`${moduleName}.map`); + moduleSourceMap = (await sourceMapResource.buffer()).toString(); + } catch (e) { + // No input sourcemap + // TODO: Differentiate real errors from file not found + } + + if (!moduleSourceMap) { + const inlineSourcemap = moduleCode.match(sourcemapPattern); + if (inlineSourcemap) { + moduleSourceMap = Buffer.from(inlineSourcemap[1], "base64").toString(); + } + } + // Strip sourceMappingURL from module code to be bundled + // It has no effect and might be cause for confusion + moduleCode = moduleCode.replace(/\/\/# sourceMappingURL=.*/, ""); + } + + const {code, sourceMap} = await rewriteDefine({ + targetBundleFormat: this.targetBundleFormat, + moduleCode, moduleName, moduleSourceMap + }); + if (code) { + outW.startSegment(moduleName); outW.ensureNewLine(); - const fileContent = await this.compressJS(code, resource); - outW.write( fileContent ); + if (sourceMap) { + sourceMap.sourceRoot = path.posix.relative( + path.dirname(this._bundleName), path.dirname(moduleName)); + await this.addSourceMap(sourceMap); + } + outW.write( code ); outW.ensureNewLine(); const compressedSize = outW.endSegment(); - log.verbose(" %s (%d,%d)", module, + log.verbose(" %s (%d,%d)", moduleName, resource.info != null ? resource.info.size : -1, compressedSize); } else { // keep unprocessed modules - remaining.push(module); + remaining.push(moduleName); } } else { // keep unprocessed modules - remaining.push(module); + remaining.push(moduleName); } } @@ -408,22 +432,20 @@ class BundleBuilder { const outW = this.outW; if ( /\.js$/.test(module) && (info == null || !info.requiresTopLevelScope) ) { - const compressedContent = await this.compressJS( await resource.buffer(), resource ); outW.write(`function(){`); - outW.write( compressedContent ); + outW.write( (await resource.buffer()).toString() ); this.exportGlobalNames(info); outW.ensureNewLine(); outW.write(`}`); } else if ( /\.js$/.test(module) /* implicitly: && info != null && info.requiresTopLevelScope */ ) { log.warn("**** warning: module %s requires top level scope" + " and can only be embedded as a string (requires 'eval')", module); - const compressedContent = await this.compressJS( await resource.buffer(), resource ); - outW.write( makeStringLiteral( compressedContent ) ); + outW.write( makeStringLiteral( (await resource.buffer()).toString() ) ); } else if ( /\.html$/.test(module) ) { - const fileContent = await resource.buffer(); + const fileContent = (await resource.buffer()).toString(); outW.write( makeStringLiteral( fileContent ) ); } else if ( /\.json$/.test(module) ) { - let fileContent = await resource.buffer(); + let fileContent = (await resource.buffer()).toString(); if ( this.optimize ) { try { fileContent = JSON.stringify( JSON.parse( fileContent) ); @@ -434,13 +456,13 @@ class BundleBuilder { } outW.write(makeStringLiteral(fileContent)); } else if ( /\.xml$/.test(module) ) { - let fileContent = await resource.buffer(); + let fileContent = (await resource.buffer()).toString(); if ( this.optimize ) { // For XML we use the pretty data // Do not minify if XML(View) contains an <*:pre> tag, // because whitespace of HTML
should be preserved (should only happen rarely)
- if (!xmlHtmlPrePattern.test(fileContent.toString())) {
- fileContent = pd.xmlmin(fileContent.toString(), false);
+ if (!xmlHtmlPrePattern.test(fileContent)) {
+ fileContent = pd.xmlmin(fileContent, false);
}
}
outW.write( makeStringLiteral( fileContent ) );
@@ -503,11 +525,10 @@ class BundleBuilder {
const CALL_SAP_UI_DEFINE = ["sap", "ui", "define"];
-function rewriteDefine(targetBundleFormat, code, moduleName) {
+async function rewriteDefine({targetBundleFormat, moduleCode, moduleName, moduleSourceMap}) {
let ast;
- const codeStr = code.toString();
try {
- ast = parseJS(codeStr, {range: true});
+ ast = parseJS(moduleCode, {range: true});
} catch (e) {
log.error("error while parsing %s: %s", moduleName, e.message);
return;
@@ -519,7 +540,6 @@ function rewriteDefine(targetBundleFormat, code, moduleName) {
const changes = [];
const defineCall = ast.body[0].expression;
-
// Inject module name if missing
if ( defineCall.arguments.length == 0 ||
defineCall.arguments[0].type !== Syntax.Literal ) {
@@ -537,7 +557,6 @@ function rewriteDefine(targetBundleFormat, code, moduleName) {
changes.push({
index,
- count: 0,
value
});
}
@@ -549,29 +568,81 @@ function rewriteDefine(targetBundleFormat, code, moduleName) {
changes.push({
// asterisk marks the index: sap.ui.*define()
index: defineCall.callee.property.range[0],
- count: 0,
value: "pre"
});
}
-
- return applyChanges(codeStr, changes);
+ if (moduleSourceMap === null) {
+ log.info(`No input source map available for module ${moduleName}`);
+ }
+ return transform(moduleCode, changes, moduleSourceMap);
}
return false;
}
-function applyChanges(string, changes) {
- // No sorting needed as changes are added in correct order
+async function transform(code, changes, inputSourceMap) {
+ const mappingChanges = [];
+ const sourceMap = inputSourceMap ? JSON.parse(inputSourceMap) : null;
- const array = Array.from(string);
+ const array = Array.from(code);
+ // No sorting needed as changes are added in correct (reverse) order
changes.forEach((change) => {
+ if (sourceMap) {
+ // Compute line and column for given index to re-align source map with inserted characters
+ const precedingCode = array.slice(0, change.index);
+
+ const line = precedingCode.reduce((lineCount, char) => {
+ if (char === "\n") {
+ lineCount++;
+ }
+ return lineCount;
+ }, 0);
+ const lineStartIndex = precedingCode.lastIndexOf("\n") + 1;
+ const column = change.index - lineStartIndex;
+
+ mappingChanges.push({
+ line,
+ column,
+ columnDiff: change.value.length
+ });
+ }
+
+ // Apply modification
array.splice(
change.index,
- change.count,
+ 0,
change.value
);
});
- return array.join("");
-}
+ const transformedCode = array.join("");
+
+ if (sourceMap) {
+ // Source map re-alignment needs to be done from front to back
+ mappingChanges.reverse();
+
+ const mappings = decodeMappings(sourceMap.mappings);
+ mappingChanges.forEach((mappingChange) => {
+ const lineMapping = mappings[mappingChange.line];
+
+ // Mapping structure:
+ // [generatedCodeColumn, sourceIndex, sourceCodeLine, sourceCodeColumn, nameIndex]
+ lineMapping.forEach((mapping) => {
+ if (mapping[0] > mappingChange.column) {
+ // All column mappings for the generated code after any change
+ // need to be moved by the amount of inserted characters
+ mapping[0] = mapping[0] + mappingChange.columnDiff;
+ }
+ });
+ });
+ sourceMap.mappings = encodeMappings(mappings);
+
+ // No need for file information in source map since the bundled code does not exist in any file anyways
+ delete sourceMap.file;
+ }
+ return {
+ code: transformedCode,
+ sourceMap
+ };
+}
module.exports = BundleBuilder;
diff --git a/lib/lbt/bundle/BundleWriter.js b/lib/lbt/bundle/BundleWriter.js
index 8b63ba0ad..004bc9311 100644
--- a/lib/lbt/bundle/BundleWriter.js
+++ b/lib/lbt/bundle/BundleWriter.js
@@ -11,6 +11,8 @@ const SPACES_OR_TABS_ONLY = /^[ \t]+$/;
*
* Most methods have been extracted from JSMergeWriter.
*
+ * columnOffset and lineOffset are used for sourcemap merging as reference to where we are at a given point in time
+ *
* @author Frank Weigel
* @since 1.27.0
* @private
@@ -18,6 +20,8 @@ const SPACES_OR_TABS_ONLY = /^[ \t]+$/;
class BundleWriter {
constructor() {
this.buf = "";
+ this.lineOffset = 0;
+ this.columnOffset = 0;
this.segments = [];
this.currentSegment = null;
this.currentSourceIndex = 0;
@@ -28,6 +32,11 @@ class BundleWriter {
let writeBuf = "";
for ( let i = 0; i < str.length; i++ ) {
writeBuf += str[i];
+ if (str[i] != null && str[i].split) {
+ const strSplit = str[i].split(NL);
+ this.lineOffset += strSplit.length - 1;
+ this.columnOffset += strSplit[strSplit.length - 1].length;
+ }
}
if ( writeBuf.length >= 1 ) {
this.buf += writeBuf;
@@ -40,15 +49,23 @@ class BundleWriter {
writeln(...str) {
for ( let i = 0; i < str.length; i++ ) {
this.buf += str[i];
+ if (str[i] != null && str[i].split) {
+ const strSplit = str[i].split(NL);
+ this.lineOffset += strSplit.length - 1;
+ }
}
this.buf += NL;
this.endsWithNewLine = true;
+ this.lineOffset += 1;
+ this.columnOffset = 0;
}
ensureNewLine() {
if ( !this.endsWithNewLine ) {
this.buf += NL;
this.endsWithNewLine = true;
+ this.lineOffset += 1;
+ this.columnOffset = 0;
}
}
diff --git a/lib/processors/bundlers/moduleBundler.js b/lib/processors/bundlers/moduleBundler.js
index 39498f86f..3cfdd9420 100644
--- a/lib/processors/bundlers/moduleBundler.js
+++ b/lib/processors/bundlers/moduleBundler.js
@@ -142,13 +142,20 @@ module.exports = function({resources, options: {bundleDefinition, bundleOptions}
return Promise.all(bundles.map((bundleObj) => {
if ( bundleObj ) {
- const {name, content} = bundleObj;
+ const {name, content, sourceMap} = bundleObj;
// console.log("creating bundle as '%s'", "/resources/" + name);
const resource = new EvoResource({
path: "/resources/" + name,
string: content
});
- return resource;
+ const sourceMapResource = new EvoResource({
+ path: "/resources/" + name + ".map",
+ string: sourceMap
+ });
+ return {
+ bundle: resource,
+ sourceMap: sourceMapResource
+ };
}
}));
});
diff --git a/lib/tasks/bundlers/generateBundle.js b/lib/tasks/bundlers/generateBundle.js
index 781d09a02..8a9cd8393 100644
--- a/lib/tasks/bundlers/generateBundle.js
+++ b/lib/tasks/bundlers/generateBundle.js
@@ -30,7 +30,7 @@ module.exports = function({
}]
});
- return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library}").then((resources) => {
+ return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}").then((resources) => {
return moduleBundler({
options: {
bundleDefinition,
@@ -38,11 +38,14 @@ module.exports = function({
},
resources
}).then((bundles) => {
- return Promise.all(bundles.map((bundle) => {
+ return Promise.all(bundles.map(({bundle, sourceMap}) => {
if (taskUtil) {
taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
}
- return workspace.write(bundle);
+ return Promise.all([
+ workspace.write(bundle),
+ workspace.write(sourceMap)
+ ]);
}));
});
});
diff --git a/lib/tasks/bundlers/generateComponentPreload.js b/lib/tasks/bundlers/generateComponentPreload.js
index 454ba4cb0..4cc72c631 100644
--- a/lib/tasks/bundlers/generateComponentPreload.js
+++ b/lib/tasks/bundlers/generateComponentPreload.js
@@ -40,7 +40,7 @@ module.exports = function({
});
// TODO 3.0: Limit to workspace resources?
- return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library}")
+ return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}")
.then(async (resources) => {
let allNamespaces = [];
if (paths) {
@@ -148,11 +148,14 @@ module.exports = function({
}));
})
.then((processedResources) => {
- return Promise.all(processedResources.map((resource) => {
+ return Promise.all(processedResources.map(([{bundle, sourceMap}]) => {
if (taskUtil) {
- taskUtil.setTag(resource[0], taskUtil.STANDARD_TAGS.IsBundle);
+ taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
}
- return workspace.write(resource[0]);
+ return Promise.all([
+ workspace.write(bundle),
+ workspace.write(sourceMap)
+ ]);
}));
});
};
diff --git a/lib/tasks/bundlers/generateLibraryPreload.js b/lib/tasks/bundlers/generateLibraryPreload.js
index ef67ced79..d61bb56fc 100644
--- a/lib/tasks/bundlers/generateLibraryPreload.js
+++ b/lib/tasks/bundlers/generateLibraryPreload.js
@@ -283,7 +283,7 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
}]
});
- return combo.byGlob("/**/*.{js,json,xml,html,properties,library}").then((resources) => {
+ return combo.byGlob("/**/*.{js,json,xml,html,properties,library,js.map}").then((resources) => {
// Find all libraries and create a library-preload.js bundle
let p;
@@ -330,11 +330,14 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
}),
]).then((results) => {
const bundles = Array.prototype.concat.apply([], results);
- return Promise.all(bundles.map((bundle) => {
+ return Promise.all(bundles.map(({bundle, sourceMap}) => {
if (taskUtil) {
taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
}
- return workspace.write(bundle);
+ return Promise.all([
+ workspace.write(bundle),
+ workspace.write(sourceMap)
+ ]);
}));
});
} else {
@@ -373,12 +376,15 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
return createLibraryBundles(libraryNamespace, resources, excludes)
.then((results) => {
const bundles = Array.prototype.concat.apply([], results);
- return Promise.all(bundles.map((bundle) => {
+ return Promise.all(bundles.map(({bundle, sourceMap} = {}) => {
if (bundle) {
if (taskUtil) {
taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
}
- return workspace.write(bundle);
+ return Promise.all([
+ workspace.write(bundle),
+ workspace.write(sourceMap)
+ ]);
}
}));
});
diff --git a/package-lock.json b/package-lock.json
index f47a66bbe..8132e48a2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -617,6 +617,14 @@
"@vue/shared": "3.2.20",
"estree-walker": "^2.0.2",
"source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
}
},
"@vue/compiler-dom": {
@@ -645,6 +653,14 @@
"magic-string": "^0.25.7",
"postcss": "^8.1.10",
"source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
}
},
"@vue/compiler-ssr": {
@@ -1840,6 +1856,13 @@
"inherits": "^2.0.4",
"source-map": "^0.6.1",
"source-map-resolve": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
}
},
"css-select": {
@@ -3385,6 +3408,14 @@
"debug": "^4.1.1",
"istanbul-lib-coverage": "^3.0.0",
"source-map": "^0.6.1"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ }
}
},
"istanbul-reports": {
@@ -5151,11 +5182,6 @@
}
}
},
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
- },
"source-map-js": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz",
@@ -5178,13 +5204,19 @@
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+ }
}
},
"sourcemap-codec": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
- "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
- "dev": true
+ "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
},
"spawn-wrap": {
"version": "2.0.0",
diff --git a/package.json b/package.json
index 4ea401446..48fb0ba30 100644
--- a/package.json
+++ b/package.json
@@ -120,6 +120,7 @@
"replacestream": "^4.0.3",
"rimraf": "^3.0.2",
"semver": "^7.3.5",
+ "sourcemap-codec": "^1.4.8",
"terser": "^5.9.0",
"xml2js": "^0.4.23",
"yazl": "^2.5.1"
diff --git a/test/lib/lbt/bundle/Builder.js b/test/lib/lbt/bundle/Builder.js
index 9eb8228e6..69b47aba5 100644
--- a/test/lib/lbt/bundle/Builder.js
+++ b/test/lib/lbt/bundle/Builder.js
@@ -619,3 +619,690 @@ sap.ui.loader.config({bundlesUI5:{
t.deepEqual(oResult.bundleInfo.subModules, ["a.js", "b.js"],
"bundle info subModules are correct");
});
+
+test("integration: createBundle using predefine calls with source maps and a single, simple source", async (t) => {
+ const pool = new ResourcePool();
+ pool.addResource({
+ name: "jquery.sap.global-dbg.js",
+ buffer: async () => `/* Some comment */
+sap.ui.define([], function (){
+ console.log("Put me on a map!");
+ return {};
+});`
+ });
+
+ const originalSourceMap = {
+ "version": 3,
+ "sources":
+ [
+ "jquery.sap.global-dbg.js"
+ ],
+ "names":
+ [
+ "sap",
+ "ui",
+ "define",
+ "console",
+ "log"
+ ],
+ "mappings": "AACAA,IAAIC,GAAGC,OAAO,GAAI,WACjBC,QAAQC,IAAI,oBACZ,MAAO",
+ "file": "jquery.sap.global.js"
+ };
+ pool.addResource({
+ name: "jquery.sap.global.js.map",
+ buffer: async () => JSON.stringify(originalSourceMap)
+ });
+ pool.addResource({
+ name: "jquery.sap.global.js",
+ buffer: async () => `sap.ui.define([],function(){console.log("Put me on a map!");return{}});
+//# sourceMappingURL=jquery.sap.global.js.map`
+ });
+
+ const bundleDefinition = {
+ name: `Component-preload.js`,
+ defaultFileTypes: [".js"],
+ sections: [{
+ mode: "preload",
+ name: "preload-section",
+ filters: [
+ "jquery.sap.global.js"
+ ]
+ }]
+ };
+
+ const builder = new Builder(pool);
+ const oResult = await builder.createBundle(bundleDefinition, {
+ usePredefineCalls: true,
+ numberOfParts: 1,
+ decorateBootstrapModule: true,
+ optimize: false
+ });
+ t.deepEqual(oResult.name, "Component-preload.js");
+ const expectedContent = `//@ui5-bundle Component-preload.js
+sap.ui.predefine("jquery.sap.global", [],function(){console.log("Put me on a map!");return{}});
+//# sourceMappingURL=Component-preload.js.map
+`;
+ t.deepEqual(oResult.content, expectedContent, "Correct bundle content");
+ t.deepEqual(oResult.bundleInfo.name, "Component-preload.js", "bundle info name is correct");
+ t.deepEqual(oResult.bundleInfo.size, expectedContent.length, "bundle info size is correct");
+ t.deepEqual(oResult.bundleInfo.subModules,
+ [
+ "jquery.sap.global.js"
+ ], "bundle info subModules are correct");
+ const indexMap = JSON.parse(oResult.sourceMap);
+ t.is(indexMap.sections.length, 1, "Bundle index source map contains one section");
+ t.deepEqual(indexMap.sections[0].offset, {
+ line: 1,
+ column: 0
+ }, "Section has correct offset");
+
+ const expectedSourceMap = {
+ "version": 3,
+ "sources":
+ [
+ "jquery.sap.global-dbg.js"
+ ],
+ "names":
+ [
+ "sap",
+ "ui",
+ "define",
+ "console",
+ "log"
+ ],
+ "mappings": "AACAA,IAAIC,GAAGC,+BAAO,GAAI,WACjBC,QAAQC,IAAI,oBACZ,MAAO",
+ "sourceRoot": ""
+ };
+ t.deepEqual(indexMap.sections[0].map, expectedSourceMap, "Section contains correct map");
+});
+
+test("integration: createBundle using predefine calls with source maps and a single, multi-line source", async (t) => {
+ const pool = new ResourcePool();
+ pool.addResource({
+ name: "jquery.sap.global-dbg.js",
+ buffer: async () => `/* Some comment */
+sap.
+ui.
+define(
+[
+], function (){
+ console.log("Put me on a map!");
+ return {};
+});`
+ });
+
+ const originalSourceMap = {
+ "version": 3,
+ "sources":
+ [
+ "jquery.sap.global-dbg.js"
+ ],
+ "names":
+ [
+ "sap",
+ "ui",
+ "define",
+ "console",
+ "log"
+ ],
+ "mappings": "AACAA,IACAC,GACAC,OACA,GACG,WACFC,QAAQC,IAAI,oBACZ,MAAO",
+ "file": "jquery.sap.global.js"
+ };
+ pool.addResource({
+ name: "jquery.sap.global.js.map",
+ buffer: async () => JSON.stringify(originalSourceMap)
+ });
+ pool.addResource({
+ name: "jquery.sap.global.js",
+ buffer: async () => `sap.ui.define([],function(){console.log("Put me on a map!");return{}});
+//# sourceMappingURL=jquery.sap.global.js.map`
+ });
+
+ const bundleDefinition = {
+ name: `Component-preload.js`,
+ defaultFileTypes: [".js"],
+ sections: [{
+ mode: "preload",
+ name: "preload-section",
+ filters: [
+ "jquery.sap.global.js"
+ ]
+ }]
+ };
+
+ const builder = new Builder(pool);
+ const oResult = await builder.createBundle(bundleDefinition, {
+ usePredefineCalls: true,
+ numberOfParts: 1,
+ decorateBootstrapModule: true,
+ optimize: false
+ });
+ t.deepEqual(oResult.name, "Component-preload.js");
+ const expectedContent = `//@ui5-bundle Component-preload.js
+sap.ui.predefine("jquery.sap.global", [],function(){console.log("Put me on a map!");return{}});
+//# sourceMappingURL=Component-preload.js.map
+`;
+ t.deepEqual(oResult.content, expectedContent, "Correct bundle content");
+ t.deepEqual(oResult.bundleInfo.name, "Component-preload.js", "bundle info name is correct");
+ t.deepEqual(oResult.bundleInfo.size, expectedContent.length, "bundle info size is correct");
+ t.deepEqual(oResult.bundleInfo.subModules,
+ [
+ "jquery.sap.global.js"
+ ], "bundle info subModules are correct");
+ const indexMap = JSON.parse(oResult.sourceMap);
+ t.is(indexMap.sections.length, 1, "Bundle index source map contains one section");
+ t.deepEqual(indexMap.sections[0].offset, {
+ line: 1,
+ column: 0
+ }, "Section has correct offset");
+
+ const expectedSourceMap = {
+ "version": 3,
+ "sources":
+ [
+ "jquery.sap.global-dbg.js"
+ ],
+ "names":
+ [
+ "sap",
+ "ui",
+ "define",
+ "console",
+ "log"
+ ],
+ "mappings": "AACAA,IACAC,GACAC,+BACA,GACG,WACFC,QAAQC,IAAI,oBACZ,MAAO",
+ "sourceRoot": ""
+ };
+ t.deepEqual(indexMap.sections[0].map, expectedSourceMap, "Section contains correct map");
+});
+
+test("integration: createBundle using predefine calls with source maps and a single source", async (t) => {
+ const pool = new ResourcePool();
+ pool.addResource({
+ name: "jquery.sap.global-dbg.js",
+ buffer: async () => `/*!
+ * OpenUI5
+ * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
+ */
+
+/*global XMLHttpRequest, localStorage, alert, document */
+
+/**
+ * @namespace jQuery
+ * @public
+ */
+sap.ui.define([
+ // new sap/base/* modules
+ "sap/base/util/now", "sap/base/util/Version", "sap/base/assert", "sap/base/Log"
+], function(now, Version, assert, Log) {
+ return now;
+});`
+ });
+
+ const originalSourceMap = {
+ "version": 3,
+ "sources":
+ [
+ "jquery.sap.global-dbg.js"
+ ],
+ "names":
+ [
+ "sap",
+ "ui",
+ "define",
+ "now",
+ "Version",
+ "assert",
+ "Log"
+ ],
+ "mappings": ";;;;;AAYAA,IAAIC,GAAGC,OAAO,CAEb,oBAAqB,wBAAyB,kBAAmB,gBAC/D,SAASC,EAAKC,EAASC,EAAQC,GACjC,OAAOH",
+ "file": "jquery.sap.global.js"
+ };
+ pool.addResource({
+ name: "jquery.sap.global.js.map",
+ buffer: async () => JSON.stringify(originalSourceMap)
+ });
+ pool.addResource({
+ name: "jquery.sap.global.js",
+ buffer: async () => `/*!
+ * OpenUI5
+ * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
+ */
+sap.ui.define(["sap/base/util/now","sap/base/util/Version","sap/base/assert","sap/base/Log"],function(s,a,e,i){return s});
+//# sourceMappingURL=jquery.sap.global.js.map`
+ });
+
+ const bundleDefinition = {
+ name: `Component-preload.js`,
+ defaultFileTypes: [".js"],
+ sections: [{
+ mode: "preload",
+ name: "preload-section",
+ filters: [
+ "jquery.sap.global.js"
+ ]
+ }]
+ };
+
+ const builder = new Builder(pool);
+ const oResult = await builder.createBundle(bundleDefinition, {
+ usePredefineCalls: true,
+ numberOfParts: 1,
+ decorateBootstrapModule: true,
+ optimize: false
+ });
+ t.deepEqual(oResult.name, "Component-preload.js");
+ const expectedContent = `//@ui5-bundle Component-preload.js
+/*!
+ * OpenUI5
+ * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
+ */
+sap.ui.predefine("jquery.sap.global", ["sap/base/util/now","sap/base/util/Version","sap/base/assert","sap/base/Log"],function(s,a,e,i){return s});
+//# sourceMappingURL=Component-preload.js.map
+`;
+ t.deepEqual(oResult.content, expectedContent, "Correct bundle content");
+ t.deepEqual(oResult.bundleInfo.name, "Component-preload.js", "bundle info name is correct");
+ t.deepEqual(oResult.bundleInfo.size, expectedContent.length, "bundle info size is correct");
+ t.deepEqual(oResult.bundleInfo.subModules,
+ [
+ "jquery.sap.global.js"
+ ], "bundle info subModules are correct");
+ const indexMap = JSON.parse(oResult.sourceMap);
+ t.is(indexMap.sections.length, 1, "Bundle index source map contains one section");
+ t.deepEqual(indexMap.sections[0].offset, {
+ line: 1,
+ column: 0
+ }, "Section has correct offset");
+
+ const expectedSourceMap = {
+ "version": 3,
+ "sources":
+ [
+ "jquery.sap.global-dbg.js"
+ ],
+ "names":
+ [
+ "sap",
+ "ui",
+ "define",
+ "now",
+ "Version",
+ "assert",
+ "Log"
+ ],
+ "mappings": ";;;;;AAYAA,IAAIC,GAAGC,+BAAO,CAEb,oBAAqB,wBAAyB,kBAAmB,gBAC/D,SAASC,EAAKC,EAASC,EAAQC,GACjC,OAAOH",
+ "sourceRoot": ""
+ };
+ t.deepEqual(indexMap.sections[0].map, expectedSourceMap, "Section contains correct map");
+});
+
+test("integration: createBundle using predefine calls with source maps and a multiple source", async (t) => {
+ const pool = new ResourcePool();
+ pool.addResource({
+ name: "jquery.sap.global-dbg.js",
+ buffer: async () => `/*!
+ * OpenUI5
+ * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
+ */
+
+/*global XMLHttpRequest, localStorage, alert, document */
+
+/**
+ * @namespace jQuery
+ * @public
+ */
+sap.ui.define([
+ // new sap/base/* modules
+ "sap/base/util/now", "sap/base/util/Version", "sap/base/assert", "sap/base/Log"
+], function(now, Version, assert, Log) {
+ return now;
+});`
+ });
+
+ const originalGlobalSourceMap = {
+ "version": 3,
+ "sources":
+ [
+ "jquery.sap.global-dbg.js"
+ ],
+ "names":
+ [
+ "sap",
+ "ui",
+ "define",
+ "now",
+ "Version",
+ "assert",
+ "Log"
+ ],
+ "mappings": ";;;;;AAYAA,IAAIC,GAAGC,OAAO,CAEb,oBAAqB,wBAAyB,kBAAmB,gBAC/D,SAASC,EAAKC,EAASC,EAAQC,GACjC,OAAOH",
+ "file": "jquery.sap.global.js"
+ };
+ pool.addResource({
+ name: "jquery.sap.global.js.map",
+ buffer: async () => JSON.stringify(originalGlobalSourceMap)
+ });
+ pool.addResource({
+ name: "jquery.sap.global.js",
+ buffer: async () => `/*!
+ * OpenUI5
+ * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
+ */
+sap.ui.define(["sap/base/util/now","sap/base/util/Version","sap/base/assert","sap/base/Log"],function(s,a,e,i){return s});
+//# sourceMappingURL=jquery.sap.global.js.map`
+ });
+
+ pool.addResource({
+ name: "jquery.sap.dom-dbg.js",
+ buffer: async () => `/*!
+ * OpenUI5
+ * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
+ */
+
+// Provides functionality related to DOM analysis and manipulation which is not provided by jQuery itself.
+sap.ui.define([
+ 'jquery.sap.global', 'sap/ui/dom/containsOrEquals',
+ 'sap/ui/core/syncStyleClass', 'sap/ui/dom/getOwnerWindow', 'sap/ui/dom/getScrollbarSize',
+ 'sap/ui/dom/denormalizeScrollLeftRTL', 'sap/ui/dom/denormalizeScrollBeginRTL',
+ 'sap/ui/dom/units/Rem', 'sap/ui/dom/jquery/Aria',
+ 'sap/ui/dom/jquery/Selection', 'sap/ui/dom/jquery/zIndex', 'sap/ui/dom/jquery/parentByAttribute',
+ 'sap/ui/dom/jquery/cursorPos', 'sap/ui/dom/jquery/selectText', 'sap/ui/dom/jquery/getSelectedText',
+ 'sap/ui/dom/jquery/rect', 'sap/ui/dom/jquery/rectContains', 'sap/ui/dom/jquery/Focusable',
+ 'sap/ui/dom/jquery/hasTabIndex', 'sap/ui/dom/jquery/scrollLeftRTL', 'sap/ui/dom/jquery/scrollRightRTL', 'sap/ui/dom/jquery/Selectors'
+], function(jQuery, domContainsOrEquals, fnSyncStyleClass, domGetOwnerWindow,
+ domGetScrollbarSize, domDenormalizeScrollLeftRTL, domDenormalizeScrollBeginRTL, domUnitsRem
+ /*
+ jqueryAria,
+ jquerySelection,
+ jqueryzIndex,
+ jqueryParentByAttribute,
+ jqueryCursorPos,
+ jquerySelectText,
+ jqueryGetSelectedText,
+ jqueryRect,
+ jqueryRectContains,
+ jqueryFocusable,
+ jqueryHasTabIndex,
+ jqueryScrollLeftRTL,
+ jqueryScrollRightRTL,
+ jquerySelectors*/
+) {
+ "use strict";
+
+ /**
+ * Shortcut for document.getElementById().
+ *
+ * @param {string} sId The id of the DOM element to return
+ * @param {Window} [oWindow=window] The window (optional)
+ * @return {Element} The DOMNode identified by the given sId
+ * @public
+ * @since 0.9.0
+ * @deprecated since 1.58 use document.getElementById
instead
+ */
+ jQuery.sap.domById = function domById(sId, oWindow) {
+ return sId ? (oWindow || window).document.getElementById(sId) : null;
+ };
+
+ return jQuery;
+
+});`
+ });
+
+ const originalDomSourceMap = {
+ "version": 3,
+ "sources":
+ [
+ "jquery.sap.dom-dbg.js"
+ ],
+ "names":
+ [
+ "sap",
+ "ui",
+ "define",
+ "jQuery",
+ "domContainsOrEquals",
+ "fnSyncStyleClass",
+ "domGetOwnerWindow",
+ "domGetScrollbarSize",
+ "domDenormalizeScrollLeftRTL",
+ "domDenormalizeScrollBeginRTL",
+ "domUnitsRem",
+ "domById",
+ "sId",
+ "oWindow",
+ "window",
+ "document",
+ "getElementById"
+ ],
+ "mappings": ";;;;;AAOAA,IAAIC,GAAGC,OAAO,CACb,oBAAqB,8BACrB,6BAA8B,4BAA6B,8BAC3D,sCAAuC,uCACvC,uBAAwB,yBACxB,8BAA+B,2BAA4B,sCAC3D,8BAA+B,+BAAgC,oCAC/D,yBAA0B,iCAAkC,8BAC5D,gCAAiC,kCAAmC,mCAAoC,+BACtG,SAASC,OAAQC,EAAqBC,EAAkBC,EAC1DC,EAAqBC,EAA6BC,EAA8BC,GAiBhF,aAYAP,OAAOH,IAAIW,QAAU,SAASA,EAAQC,EAAKC,GAC1C,OAAOD,GAAOC,GAAWC,QAAQC,SAASC,eAAeJ,GAAO,MAGjE,OAAOT",
+ "file": "jquery.sap.dom.js"
+ };
+ pool.addResource({
+ name: "jquery.sap.dom.js.map",
+ buffer: async () => JSON.stringify(originalDomSourceMap)
+ });
+ pool.addResource({
+ name: "jquery.sap.dom.js",
+ buffer: async () => `/*!
+ * OpenUI5
+ * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
+ */
+sap.ui.define(["jquery.sap.global","sap/ui/dom/containsOrEquals","sap/ui/core/syncStyleClass","sap/ui/dom/getOwnerWindow","sap/ui/dom/getScrollbarSize","sap/ui/dom/denormalizeScrollLeftRTL","sap/ui/dom/denormalizeScrollBeginRTL","sap/ui/dom/units/Rem","sap/ui/dom/jquery/Aria","sap/ui/dom/jquery/Selection","sap/ui/dom/jquery/zIndex","sap/ui/dom/jquery/parentByAttribute","sap/ui/dom/jquery/cursorPos","sap/ui/dom/jquery/selectText","sap/ui/dom/jquery/getSelectedText","sap/ui/dom/jquery/rect","sap/ui/dom/jquery/rectContains","sap/ui/dom/jquery/Focusable","sap/ui/dom/jquery/hasTabIndex","sap/ui/dom/jquery/scrollLeftRTL","sap/ui/dom/jquery/scrollRightRTL","sap/ui/dom/jquery/Selectors"],function(jQuery,e,u,o,s,i,r,a){"use strict";jQuery.sap.domById=function e(u,o){return u?(o||window).document.getElementById(u):null};return jQuery});
+//# sourceMappingURL=jquery.sap.dom.js.map`
+ });
+
+ const bundleDefinition = {
+ name: `Component-preload.js`,
+ defaultFileTypes: [".js"],
+ sections: [{
+ mode: "preload",
+ name: "preload-section",
+ filters: [
+ "jquery.sap.global.js",
+ "jquery.sap.dom.js"
+ ]
+ }]
+ };
+
+ const builder = new Builder(pool);
+ const oResult = await builder.createBundle(bundleDefinition, {
+ usePredefineCalls: true,
+ numberOfParts: 1,
+ decorateBootstrapModule: true,
+ optimize: false
+ });
+ t.deepEqual(oResult.name, "Component-preload.js");
+ const expectedContent = `//@ui5-bundle Component-preload.js
+/*!
+ * OpenUI5
+ * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
+ */
+sap.ui.predefine("jquery.sap.dom", ["jquery.sap.global","sap/ui/dom/containsOrEquals","sap/ui/core/syncStyleClass","sap/ui/dom/getOwnerWindow","sap/ui/dom/getScrollbarSize","sap/ui/dom/denormalizeScrollLeftRTL","sap/ui/dom/denormalizeScrollBeginRTL","sap/ui/dom/units/Rem","sap/ui/dom/jquery/Aria","sap/ui/dom/jquery/Selection","sap/ui/dom/jquery/zIndex","sap/ui/dom/jquery/parentByAttribute","sap/ui/dom/jquery/cursorPos","sap/ui/dom/jquery/selectText","sap/ui/dom/jquery/getSelectedText","sap/ui/dom/jquery/rect","sap/ui/dom/jquery/rectContains","sap/ui/dom/jquery/Focusable","sap/ui/dom/jquery/hasTabIndex","sap/ui/dom/jquery/scrollLeftRTL","sap/ui/dom/jquery/scrollRightRTL","sap/ui/dom/jquery/Selectors"],function(jQuery,e,u,o,s,i,r,a){"use strict";jQuery.sap.domById=function e(u,o){return u?(o||window).document.getElementById(u):null};return jQuery});
+/*!
+ * OpenUI5
+ * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
+ */
+sap.ui.predefine("jquery.sap.global", ["sap/base/util/now","sap/base/util/Version","sap/base/assert","sap/base/Log"],function(s,a,e,i){return s});
+//# sourceMappingURL=Component-preload.js.map
+`;
+ t.deepEqual(oResult.content, expectedContent, "Correct bundle content");
+ t.deepEqual(oResult.bundleInfo.name, "Component-preload.js", "bundle info name is correct");
+ t.deepEqual(oResult.bundleInfo.size, expectedContent.length, "bundle info size is correct");
+ t.deepEqual(oResult.bundleInfo.subModules,
+ [
+ "jquery.sap.dom.js",
+ "jquery.sap.global.js"
+ ], "bundle info subModules are correct");
+ const indexMap = JSON.parse(oResult.sourceMap);
+ t.is(indexMap.sections.length, 2, "Bundle index source map contains two sections");
+ t.deepEqual(indexMap.sections[0].offset, {
+ line: 1,
+ column: 0
+ }, "Section one has correct offset");
+
+ const expectedSourceMap1 = {
+ "version": 3,
+ "sources":
+ [
+ "jquery.sap.dom-dbg.js"
+ ],
+ "names":
+ [
+ "sap",
+ "ui",
+ "define",
+ "jQuery",
+ "domContainsOrEquals",
+ "fnSyncStyleClass",
+ "domGetOwnerWindow",
+ "domGetScrollbarSize",
+ "domDenormalizeScrollLeftRTL",
+ "domDenormalizeScrollBeginRTL",
+ "domUnitsRem",
+ "domById",
+ "sId",
+ "oWindow",
+ "window",
+ "document",
+ "getElementById"
+ ],
+ "mappings": ";;;;;AAOAA,IAAIC,GAAGC,4BAAO,CACb,oBAAqB,8BACrB,6BAA8B,4BAA6B,8BAC3D,sCAAuC,uCACvC,uBAAwB,yBACxB,8BAA+B,2BAA4B,sCAC3D,8BAA+B,+BAAgC,oCAC/D,yBAA0B,iCAAkC,8BAC5D,gCAAiC,kCAAmC,mCAAoC,+BACtG,SAASC,OAAQC,EAAqBC,EAAkBC,EAC1DC,EAAqBC,EAA6BC,EAA8BC,GAiBhF,aAYAP,OAAOH,IAAIW,QAAU,SAASA,EAAQC,EAAKC,GAC1C,OAAOD,GAAOC,GAAWC,QAAQC,SAASC,eAAeJ,GAAO,MAGjE,OAAOT",
+ "sourceRoot": ""
+ };
+ t.deepEqual(indexMap.sections[0].map, expectedSourceMap1, "Section one contains correct map");
+ t.deepEqual(indexMap.sections[1].offset, {
+ line: 7,
+ column: 0
+ }, "Section two has correct offset");
+
+ const expectedSourceMap2 = {
+ "version": 3,
+ "sources":
+ [
+ "jquery.sap.global-dbg.js"
+ ],
+ "names":
+ [
+ "sap",
+ "ui",
+ "define",
+ "now",
+ "Version",
+ "assert",
+ "Log"
+ ],
+ "mappings": ";;;;;AAYAA,IAAIC,GAAGC,+BAAO,CAEb,oBAAqB,wBAAyB,kBAAmB,gBAC/D,SAASC,EAAKC,EAASC,EAAQC,GACjC,OAAOH",
+ "sourceRoot": ""
+ };
+ t.deepEqual(indexMap.sections[1].map, expectedSourceMap2, "Section two contains correct map");
+});
+
+test("integration: createBundle using predefine calls with inline source maps and a single source", async (t) => {
+ const pool = new ResourcePool();
+ pool.addResource({
+ name: "jquery.sap.global-dbg.js",
+ buffer: async () => `/*!
+ * OpenUI5
+ * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
+ */
+
+/*global XMLHttpRequest, localStorage, alert, document */
+
+/**
+ * @namespace jQuery
+ * @public
+ */
+sap.ui.define([
+ // new sap/base/* modules
+ "sap/base/util/now", "sap/base/util/Version", "sap/base/assert", "sap/base/Log"
+], function(now, Version, assert, Log) {
+ return now;
+});`
+ });
+
+ // Source map should be identical to "single source" test above
+ pool.addResource({
+ name: "jquery.sap.global.js",
+ buffer: async () => `/*!
+ * OpenUI5
+ * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
+ */
+sap.ui.define(["sap/base/util/now","sap/base/util/Version","sap/base/assert","sap/base/Log"],function(s,a,e,i){return s});
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImpxdWVyeS5zYXAuZ2xvYmFsLWRiZy5qcyJdLCJuYW1lcyI6WyJzYXAiLCJ1aSIsImRlZmluZSIsIm5vdyIsIlZlcnNpb24iLCJhc3NlcnQiLCJMb2ciXSwibWFwcGluZ3MiOiI7Ozs7O0FBWUFBLElBQUlDLEdBQUdDLE9BQU8sQ0FFYixvQkFBcUIsd0JBQXlCLGtCQUFtQixnQkFDL0QsU0FBU0MsRUFBS0MsRUFBU0MsRUFBUUMsR0FDakMsT0FBT0giLCJmaWxlIjoianF1ZXJ5LnNhcC5nbG9iYWwuanMifQ==`
+ });
+
+ const bundleDefinition = {
+ name: `Component-preload.js`,
+ defaultFileTypes: [".js"],
+ sections: [{
+ mode: "preload",
+ name: "preload-section",
+ filters: [
+ "jquery.sap.global.js"
+ ]
+ }]
+ };
+
+ const builder = new Builder(pool);
+ const oResult = await builder.createBundle(bundleDefinition, {
+ usePredefineCalls: true,
+ numberOfParts: 1,
+ decorateBootstrapModule: true,
+ optimize: false
+ });
+ t.deepEqual(oResult.name, "Component-preload.js");
+ const expectedContent = `//@ui5-bundle Component-preload.js
+/*!
+ * OpenUI5
+ * (c) Copyright 2009-2021 SAP SE or an SAP affiliate company.
+ * Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
+ */
+sap.ui.predefine("jquery.sap.global", ["sap/base/util/now","sap/base/util/Version","sap/base/assert","sap/base/Log"],function(s,a,e,i){return s});
+//# sourceMappingURL=Component-preload.js.map
+`;
+ t.deepEqual(oResult.content, expectedContent, "Correct bundle content");
+ t.deepEqual(oResult.bundleInfo.name, "Component-preload.js", "bundle info name is correct");
+ t.deepEqual(oResult.bundleInfo.size, expectedContent.length, "bundle info size is correct");
+ t.deepEqual(oResult.bundleInfo.subModules,
+ [
+ "jquery.sap.global.js"
+ ], "bundle info subModules are correct");
+ const indexMap = JSON.parse(oResult.sourceMap);
+ t.is(indexMap.sections.length, 1, "Bundle index source map contains one section");
+ t.deepEqual(indexMap.sections[0].offset, {
+ line: 1,
+ column: 0
+ }, "Section has correct offset");
+
+ const expectedSourceMap = {
+ "version": 3,
+ "sources":
+ [
+ "jquery.sap.global-dbg.js"
+ ],
+ "names":
+ [
+ "sap",
+ "ui",
+ "define",
+ "now",
+ "Version",
+ "assert",
+ "Log"
+ ],
+ "mappings": ";;;;;AAYAA,IAAIC,GAAGC,+BAAO,CAEb,oBAAqB,wBAAyB,kBAAmB,gBAC/D,SAASC,EAAKC,EAASC,EAAQC,GACjC,OAAOH",
+ "sourceRoot": ""
+ };
+ t.deepEqual(indexMap.sections[0].map, expectedSourceMap, "Section contains correct map");
+});