@ui5/builder 3.0.0-alpha.1 → 3.0.0-alpha.4

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.
@@ -11,6 +11,8 @@ const SPACES_OR_TABS_ONLY = /^[ \t]+$/;
11
11
  *
12
12
  * Most methods have been extracted from JSMergeWriter.
13
13
  *
14
+ * columnOffset and lineOffset are used for sourcemap merging as reference to where we are at a given point in time
15
+ *
14
16
  * @author Frank Weigel
15
17
  * @since 1.27.0
16
18
  * @private
@@ -18,6 +20,8 @@ const SPACES_OR_TABS_ONLY = /^[ \t]+$/;
18
20
  class BundleWriter {
19
21
  constructor() {
20
22
  this.buf = "";
23
+ this.lineOffset = 0;
24
+ this.columnOffset = 0;
21
25
  this.segments = [];
22
26
  this.currentSegment = null;
23
27
  this.currentSourceIndex = 0;
@@ -28,6 +32,11 @@ class BundleWriter {
28
32
  let writeBuf = "";
29
33
  for ( let i = 0; i < str.length; i++ ) {
30
34
  writeBuf += str[i];
35
+ if (str[i] != null && str[i].split) {
36
+ const strSplit = str[i].split(NL);
37
+ this.lineOffset += strSplit.length - 1;
38
+ this.columnOffset += strSplit[strSplit.length - 1].length;
39
+ }
31
40
  }
32
41
  if ( writeBuf.length >= 1 ) {
33
42
  this.buf += writeBuf;
@@ -40,15 +49,23 @@ class BundleWriter {
40
49
  writeln(...str) {
41
50
  for ( let i = 0; i < str.length; i++ ) {
42
51
  this.buf += str[i];
52
+ if (str[i] != null && str[i].split) {
53
+ const strSplit = str[i].split(NL);
54
+ this.lineOffset += strSplit.length - 1;
55
+ }
43
56
  }
44
57
  this.buf += NL;
45
58
  this.endsWithNewLine = true;
59
+ this.lineOffset += 1;
60
+ this.columnOffset = 0;
46
61
  }
47
62
 
48
63
  ensureNewLine() {
49
64
  if ( !this.endsWithNewLine ) {
50
65
  this.buf += NL;
51
66
  this.endsWithNewLine = true;
67
+ this.lineOffset += 1;
68
+ this.columnOffset = 0;
52
69
  }
53
70
  }
54
71
 
@@ -1,12 +1,8 @@
1
1
  const Resource = require("./Resource");
2
2
 
3
- function extractName(path) {
4
- return path.slice( "/resources/".length);
5
- }
6
-
7
3
  class LocatorResource extends Resource {
8
- constructor(pool, resource) {
9
- super(pool, extractName(resource.getPath()), null, resource.getStatInfo());
4
+ constructor(pool, resource, moduleName) {
5
+ super(pool, moduleName, null, resource.getStatInfo());
10
6
  this.resource = resource;
11
7
  }
12
8
 
@@ -17,6 +13,10 @@ class LocatorResource extends Resource {
17
13
  getProject() {
18
14
  return this.resource._project;
19
15
  }
16
+
17
+ getPath() {
18
+ return this.resource.getPath();
19
+ }
20
20
  }
21
21
 
22
22
  module.exports = LocatorResource;
@@ -2,12 +2,16 @@ const ResourcePool = require("./ResourcePool");
2
2
  const LocatorResource = require("./LocatorResource");
3
3
 
4
4
  class LocatorResourcePool extends ResourcePool {
5
- prepare(resources) {
5
+ prepare(resources, moduleNameMapping) {
6
6
  resources = resources.filter( (res) => !res.getStatInfo().isDirectory() );
7
7
  return Promise.all(
8
- resources.map(
9
- (resource) => this.addResource( new LocatorResource(this, resource) )
10
- ).filter(Boolean)
8
+ resources.map((resource) => {
9
+ let moduleName = moduleNameMapping && moduleNameMapping[resource.getPath()];
10
+ if (!moduleName) {
11
+ moduleName = resource.getPath().slice("/resources/".length);
12
+ }
13
+ return this.addResource(new LocatorResource(this, resource, moduleName));
14
+ }).filter(Boolean)
11
15
  );
12
16
  }
13
17
  }
@@ -9,7 +9,7 @@ function parseJS(code, userOptions = {}) {
9
9
  // allowed options and their defaults
10
10
  const options = {
11
11
  comment: false,
12
- ecmaVersion: 2021,
12
+ ecmaVersion: 2021, // NOTE: Adopt JSModuleAnalyzer.js to allow new Syntax when upgrading to newer ECMA versions
13
13
  range: false,
14
14
  sourceType: "script",
15
15
  };
@@ -90,6 +90,7 @@ const log = require("@ui5/logger").getLogger("builder:processors:bundlers:module
90
90
  * @public
91
91
  * @typedef {object} ModuleBundleOptions
92
92
  * @property {boolean} [optimize=true] Whether the module bundle gets minified
93
+ * @property {boolean} [sourceMap=true] Whether to generate a source map file for the bundle
93
94
  * @property {boolean} [decorateBootstrapModule=false] If set to 'false', the module won't be decorated
94
95
  * with an optimization marker
95
96
  * @property {boolean} [addTryCatchRestartWrapper=false] Whether to wrap bootable module bundles with
@@ -101,21 +102,35 @@ const log = require("@ui5/logger").getLogger("builder:processors:bundlers:module
101
102
  */
102
103
 
103
104
  /**
104
- * Legacy preload bundler.
105
+ * Result set
106
+ *
107
+ * @public
108
+ * @typedef {object} ModuleBundlerResult
109
+ * @property {module:@ui5/fs.Resource} bundle Bundle resource
110
+ * @property {module:@ui5/fs.Resource} sourceMap Source Map
111
+ * @memberof module:@ui5/builder.processors
112
+ */
113
+
114
+ /**
115
+ * Legacy module bundler.
105
116
  *
106
117
  * @public
107
118
  * @alias module:@ui5/builder.processors.moduleBundler
108
119
  * @param {object} parameters Parameters
109
120
  * @param {module:@ui5/fs.Resource[]} parameters.resources Resources
110
121
  * @param {object} parameters.options Options
122
+ * @param {object} [parameters.options.moduleNameMapping]
123
+ Optional mapping of resource paths to module name in order to overwrite the default determination
111
124
  * @param {ModuleBundleDefinition} parameters.options.bundleDefinition Module bundle definition
112
125
  * @param {ModuleBundleOptions} [parameters.options.bundleOptions] Module bundle options
113
- * @returns {Promise<module:@ui5/fs.Resource[]>} Promise resolving with module bundle resources
126
+ * @returns {Promise<module:@ui5/builder.processors.ModuleBundlerResult[]>}
127
+ * Promise resolving with module bundle resources
114
128
  */
115
- module.exports = function({resources, options: {bundleDefinition, bundleOptions}}) {
129
+ module.exports = function({resources, options: {bundleDefinition, bundleOptions, moduleNameMapping}}) {
116
130
  // Apply defaults without modifying the passed object
117
131
  bundleOptions = Object.assign({}, {
118
132
  optimize: true,
133
+ sourceMap: true,
119
134
  decorateBootstrapModule: false,
120
135
  addTryCatchRestartWrapper: false,
121
136
  usePredefineCalls: false,
@@ -134,7 +149,7 @@ module.exports = function({resources, options: {bundleDefinition, bundleOptions}
134
149
  log.verbose(`bundleOptions: ${JSON.stringify(bundleOptions, null, 2)}`);
135
150
  }
136
151
 
137
- return pool.prepare( resources ).
152
+ return pool.prepare( resources, moduleNameMapping ).
138
153
  then( () => builder.createBundle(bundleDefinition, bundleOptions) ).
139
154
  then( (results) => {
140
155
  let bundles;
@@ -146,13 +161,20 @@ module.exports = function({resources, options: {bundleDefinition, bundleOptions}
146
161
 
147
162
  return Promise.all(bundles.map((bundleObj) => {
148
163
  if ( bundleObj ) {
149
- const {name, content} = bundleObj;
164
+ const {name, content, sourceMap} = bundleObj;
150
165
  // console.log("creating bundle as '%s'", "/resources/" + name);
151
- const resource = new EvoResource({
166
+ const res = {};
167
+ res.bundle = new EvoResource({
152
168
  path: "/resources/" + name,
153
169
  string: content
154
170
  });
155
- return resource;
171
+ if (sourceMap) {
172
+ res.sourceMap = new EvoResource({
173
+ path: "/resources/" + name + ".map",
174
+ string: sourceMap
175
+ });
176
+ }
177
+ return res;
156
178
  }
157
179
  }));
158
180
  });
@@ -34,10 +34,13 @@ const debugFileRegex = /((?:\.view|\.fragment|\.controller|\.designtime|\.suppor
34
34
  * @alias module:@ui5/builder.processors.minifier
35
35
  * @param {object} parameters Parameters
36
36
  * @param {module:@ui5/fs.Resource[]} parameters.resources List of resources to be processed
37
+ * @param {object} [parameters.options] Options
38
+ * @param {boolean} [parameters.options.addSourceMappingUrl=true]
39
+ * Whether to add a sourceMappingURL reference to the end of the minified resource
37
40
  * @returns {Promise<module:@ui5/builder.processors.MinifierResult[]>}
38
41
  * Promise resolving with object of resource, dbgResource and sourceMap
39
42
  */
40
- module.exports = async function({resources}) {
43
+ module.exports = async function({resources, options: {addSourceMappingUrl = true} = {}}) {
41
44
  return Promise.all(resources.map(async (resource) => {
42
45
  const dbgPath = resource.getPath().replace(debugFileRegex, "-dbg$1");
43
46
  const dbgResource = await resource.clone();
@@ -46,6 +49,12 @@ module.exports = async function({resources}) {
46
49
  const filename = path.posix.basename(resource.getPath());
47
50
  const code = await resource.getString();
48
51
  try {
52
+ const sourceMapOptions = {
53
+ filename
54
+ };
55
+ if (addSourceMappingUrl) {
56
+ sourceMapOptions.url = filename + ".map";
57
+ }
49
58
  const dbgFilename = path.posix.basename(dbgPath);
50
59
  const result = await terser.minify({
51
60
  // Use debug-name since this will be referenced in the source map "sources"
@@ -63,10 +72,7 @@ module.exports = async function({resources}) {
63
72
  "sap",
64
73
  ]
65
74
  },
66
- sourceMap: {
67
- filename,
68
- url: filename + ".map"
69
- }
75
+ sourceMap: sourceMapOptions
70
76
  });
71
77
  resource.setString(result.code);
72
78
  const sourceMapResource = new Resource({
@@ -108,6 +108,18 @@ class TaskUtil {
108
108
  return this._projectBuildContext.isRootProject();
109
109
  }
110
110
 
111
+ /**
112
+ * Retrieves a build option defined by its <code>key</code.
113
+ * If no option with the given <code>key</code> is stored, <code>undefined</code> is returned.
114
+ *
115
+ * @param {string} key The option key
116
+ * @returns {any|undefined} The build option (or undefined)
117
+ * @private
118
+ */
119
+ getBuildOption(key) {
120
+ return this._projectBuildContext.getOption(key);
121
+ }
122
+
111
123
  /**
112
124
  * Register a function that must be executed once the build is finished. This can be used to, for example,
113
125
  * clean up files temporarily created on the file system. If the callback returns a Promise, it will be waited for.
@@ -1,5 +1,5 @@
1
1
  const moduleBundler = require("../../processors/bundlers/moduleBundler");
2
- const ModuleName = require("../../lbt/utils/ModuleName");
2
+ const createModuleNameMapping = require("./utils/createModuleNameMapping");
3
3
  const ReaderCollectionPrioritized = require("@ui5/fs").ReaderCollectionPrioritized;
4
4
 
5
5
  /**
@@ -21,12 +21,57 @@ module.exports = function({
21
21
  workspace, dependencies, taskUtil, options: {projectName, bundleDefinition, bundleOptions}
22
22
  }) {
23
23
  let combo = new ReaderCollectionPrioritized({
24
- name: `libraryBundler - prioritize workspace over dependencies: ${projectName}`,
24
+ name: `generateBundle - prioritize workspace over dependencies: ${projectName}`,
25
25
  readers: [workspace, dependencies]
26
26
  });
27
27
 
28
+ const optimize = !bundleOptions || bundleOptions.optimize !== false;
28
29
  if (taskUtil) {
29
- const optimize = !bundleOptions || bundleOptions.optimize !== false;
30
+ /* Scenarios
31
+ 1. Optimize bundle with minification already done
32
+ Workspace:
33
+ * /resources/my/lib/Control.js [ui5:HasDebugVariant]
34
+ * /resources/my/lib/Control.js.map [ui5:HasDebugVariant]
35
+ * /resources/my/lib/Control-dbg.js [ui5:IsDebugVariant]
36
+
37
+ Bundler input:
38
+ * /resources/my/lib/Control.js
39
+ * /resources/my/lib/Control.js.map
40
+
41
+ => Filter out debug resources
42
+
43
+ 2. Optimize bundle with no minification
44
+ * /resources/my/lib/Control.js
45
+
46
+ => No action necessary
47
+
48
+ 3. Debug-bundle with minification already done
49
+ Workspace:
50
+ * /resources/my/lib/Control.js [ui5:HasDebugVariant]
51
+ * /resources/my/lib/Control.js.map [ui5:HasDebugVariant]
52
+ * /resources/my/lib/Control-dbg.js [ui5:IsDebugVariant]
53
+
54
+ Bundler input:
55
+ * /resources/my/lib/Control-dbg.js
56
+ * moduleNameMapping: [{"/resources/my/lib/Control-dbg.js": "my/lib/Control.js"}]
57
+
58
+ => Filter out minified-resources (tagged as "HasDebugVariant", incl. source maps) and rename debug-files
59
+
60
+ 4. Debug-bundle with no minification
61
+ * /resources/my/lib/Control.js
62
+
63
+ => No action necessary
64
+
65
+ 5. Bundle with external input (optimize or not), e.g. TS-project
66
+ Workspace:
67
+ * /resources/my/lib/Control.ts
68
+ * /resources/my/lib/Control.js
69
+ * /resources/my/lib/Control.js.map
70
+
71
+ Bundler input:
72
+ * /resources/my/lib/Control.js
73
+ * /resources/my/lib/Control.js.map
74
+ */
30
75
 
31
76
  // Omit -dbg files for optimize bundles and vice versa
32
77
  const filterTag = optimize ?
@@ -34,37 +79,32 @@ module.exports = function({
34
79
  combo = combo.filter(function(resource) {
35
80
  return !taskUtil.getTag(resource, filterTag);
36
81
  });
37
-
38
- if (!optimize) {
39
- // For "unoptimized" bundles, the non-debug files have already been filtered out
40
- // Now rename the debug variants to the same name so that they appear like the original
41
- // resource to the bundler
42
- combo = combo.transformer(async function(resourcePath, getResource) {
43
- if (taskUtil.getTag(resourcePath, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
44
- const resource = await getResource();
45
- const nonDbgPath = ModuleName.getNonDebugName(resource.getPath());
46
- if (!nonDbgPath) {
47
- throw new Error(`Failed to resolve non-debug name for ${resource.getPath()}`);
48
- }
49
- resource.setPath(nonDbgPath);
50
- }
51
- });
52
- }
53
82
  }
54
83
 
55
- return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library}").then((resources) => {
56
- return moduleBundler({
57
- options: {
58
- bundleDefinition,
59
- bundleOptions
60
- },
61
- resources
62
- }).then((bundles) => {
63
- return Promise.all(bundles.map((bundle) => {
84
+ return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}").then((resources) => {
85
+ const options = {bundleDefinition, bundleOptions};
86
+ if (!optimize && taskUtil) {
87
+ options.moduleNameMapping = createModuleNameMapping({resources, taskUtil});
88
+ }
89
+ return moduleBundler({options, resources}).then((bundles) => {
90
+ return Promise.all(bundles.map(({bundle, sourceMap} = {}) => {
91
+ if (!bundle) {
92
+ // Skip empty bundles
93
+ return;
94
+ }
64
95
  if (taskUtil) {
65
96
  taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
97
+ if (sourceMap) {
98
+ // Clear tag that might have been set by the minify task, in cases where
99
+ // the bundle name is identical to a source file
100
+ taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
101
+ }
102
+ }
103
+ const writes = [workspace.write(bundle)];
104
+ if (sourceMap) {
105
+ writes.push(workspace.write(sourceMap));
66
106
  }
67
- return workspace.write(bundle);
107
+ return Promise.all(writes);
68
108
  }));
69
109
  });
70
110
  });
@@ -41,7 +41,7 @@ module.exports = function({
41
41
  }
42
42
 
43
43
  // TODO 3.0: Limit to workspace resources?
44
- return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library}")
44
+ return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}")
45
45
  .then(async (resources) => {
46
46
  let allNamespaces = [];
47
47
  if (paths) {
@@ -148,12 +148,19 @@ module.exports = function({
148
148
  });
149
149
  }));
150
150
  })
151
- .then((processedResources) => {
152
- return Promise.all(processedResources.map((resource) => {
151
+ .then((results) => {
152
+ const bundles = Array.prototype.concat.apply([], results);
153
+ return Promise.all(bundles.map(({bundle, sourceMap}) => {
153
154
  if (taskUtil) {
154
- taskUtil.setTag(resource[0], taskUtil.STANDARD_TAGS.IsBundle);
155
+ taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
156
+ // Clear tag that might have been set by the minify task, in cases where
157
+ // the bundle name is identical to a source file
158
+ taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
155
159
  }
156
- return workspace.write(resource[0]);
160
+ return Promise.all([
161
+ workspace.write(bundle),
162
+ workspace.write(sourceMap)
163
+ ]);
157
164
  }));
158
165
  });
159
166
  };
@@ -1,5 +1,6 @@
1
1
  const log = require("@ui5/logger").getLogger("builder:tasks:bundlers:generateFlexChangesBundle");
2
2
  const flexChangesBundler = require("../../processors/bundlers/flexChangesBundler");
3
+ const semver = require("semver");
3
4
 
4
5
  /**
5
6
  * Task to create changesBundle.json file containing all changes stored in the /changes folder for easier consumption
@@ -68,9 +69,9 @@ module.exports = async function({workspace, taskUtil, options: {namespace}}) {
68
69
  const allResources = await workspace.byGlob(
69
70
  `${pathPrefix}/changes/*.{change,variant,ctrl_variant,ctrl_variant_change,ctrl_variant_management_change}`);
70
71
  if (allResources.length > 0) {
71
- const version = await readManifestMinUI5Version();
72
+ const version = semver.coerce(await readManifestMinUI5Version());
72
73
  let hasFlexBundleVersion = false;
73
- if (parseFloat(version) >= 1.73) {
74
+ if (semver.compare(version, "1.73.0") >= 0) {
74
75
  hasFlexBundleVersion = true;
75
76
  }
76
77
  const processedResources = await flexChangesBundler({
@@ -2,7 +2,7 @@ const log = require("@ui5/logger").getLogger("builder:tasks:bundlers:generateLib
2
2
  const moduleBundler = require("../../processors/bundlers/moduleBundler");
3
3
  const ReaderCollectionPrioritized = require("@ui5/fs").ReaderCollectionPrioritized;
4
4
  const {negateFilters} = require("../../lbt/resources/ResourceFilterList");
5
- const ModuleName = require("../../lbt/utils/ModuleName");
5
+ const createModuleNameMapping = require("./utils/createModuleNameMapping");
6
6
 
7
7
  function getDefaultLibraryPreloadFilters(namespace, excludes) {
8
8
  const filters = [
@@ -177,6 +177,8 @@ function createLibraryBundles(libraryNamespace, resources, excludes) {
177
177
  ignoreMissingModules: true,
178
178
  skipIfEmpty: true
179
179
  }
180
+ // Note: Although the bundle uses optimize=false, there is
181
+ // no moduleNameMapping needed, as support files are excluded from minification.
180
182
  },
181
183
  resources
182
184
  })
@@ -212,6 +214,10 @@ function getModuleBundlerOptions(config) {
212
214
  moduleBundlerOptions.bundleDefinition.sections.unshift(providedSection);
213
215
  }
214
216
 
217
+ if (config.moduleNameMapping) {
218
+ moduleBundlerOptions.moduleNameMapping = config.moduleNameMapping;
219
+ }
220
+
215
221
  return moduleBundlerOptions;
216
222
  }
217
223
 
@@ -285,7 +291,7 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
285
291
  });
286
292
  }
287
293
 
288
- return combo.byGlob("/**/*.{js,json,xml,html,properties,library}").then(async (resources) => {
294
+ return combo.byGlob("/**/*.{js,json,xml,html,properties,library,js.map}").then(async (resources) => {
289
295
  // Find all libraries and create a library-preload.js bundle
290
296
 
291
297
  let p = Promise.resolve();
@@ -305,6 +311,7 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
305
311
  return resource.getPath() === "/resources/ui5loader.js";
306
312
  });
307
313
 
314
+ let unoptimizedModuleNameMapping;
308
315
  let unoptimizedResources = resources;
309
316
  if (taskUtil) {
310
317
  unoptimizedResources = await new ReaderCollectionPrioritized({
@@ -313,16 +320,12 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
313
320
  }).filter(function(resource) {
314
321
  // Remove any non-debug variants
315
322
  return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.HasDebugVariant);
316
- }).transformer(async function(resourcePath, getResource) {
317
- if (taskUtil.getTag(resourcePath, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
318
- const resource = await getResource();
319
- const nonDbgPath = ModuleName.getNonDebugName(resource.getPath());
320
- if (!nonDbgPath) {
321
- throw new Error(`Failed to resolve non-debug name for ${resource.getPath()}`);
322
- }
323
- resource.setPath(nonDbgPath);
324
- }
325
- }).byGlob("/**/*.{js,json,xml,html,properties,library}");
323
+ }).byGlob("/**/*.{js,json,xml,html,properties,library,js.map}");
324
+
325
+ unoptimizedModuleNameMapping = createModuleNameMapping({
326
+ resources: unoptimizedResources,
327
+ taskUtil
328
+ });
326
329
  }
327
330
 
328
331
  let filters;
@@ -337,7 +340,10 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
337
340
  resources
338
341
  }),
339
342
  moduleBundler({
340
- options: getModuleBundlerOptions({name: "sap-ui-core-dbg.js", filters, preload: false}),
343
+ options: getModuleBundlerOptions({
344
+ name: "sap-ui-core-dbg.js", filters, preload: false,
345
+ moduleNameMapping: unoptimizedModuleNameMapping
346
+ }),
341
347
  resources: unoptimizedResources
342
348
  }),
343
349
  moduleBundler({
@@ -348,17 +354,27 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
348
354
  }),
349
355
  moduleBundler({
350
356
  options: getModuleBundlerOptions({
351
- name: "sap-ui-core-nojQuery-dbg.js", filters, preload: false, provided: true
357
+ name: "sap-ui-core-nojQuery-dbg.js", filters, preload: false, provided: true,
358
+ moduleNameMapping: unoptimizedModuleNameMapping
352
359
  }),
353
360
  resources: unoptimizedResources
354
361
  }),
355
362
  ]).then((results) => {
356
363
  const bundles = Array.prototype.concat.apply([], results);
357
- return Promise.all(bundles.map((bundle) => {
364
+ return Promise.all(bundles.map(({bundle, sourceMap}) => {
358
365
  if (taskUtil) {
359
366
  taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
367
+ if (sourceMap) {
368
+ // Clear tag that might have been set by the minify task, in cases where
369
+ // the bundle name is identical to a source file
370
+ taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
371
+ }
360
372
  }
361
- return workspace.write(bundle);
373
+ const writes = [workspace.write(bundle)];
374
+ if (sourceMap) {
375
+ writes.push(workspace.write(sourceMap));
376
+ }
377
+ return Promise.all(writes);
362
378
  }));
363
379
  });
364
380
  }
@@ -396,12 +412,22 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
396
412
  return createLibraryBundles(libraryNamespace, resources, excludes)
397
413
  .then((results) => {
398
414
  const bundles = Array.prototype.concat.apply([], results);
399
- return Promise.all(bundles.map((bundle) => {
415
+ return Promise.all(bundles.map(({bundle, sourceMap} = {}) => {
400
416
  if (bundle) {
401
417
  if (taskUtil) {
402
418
  taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
419
+ if (sourceMap) {
420
+ // Clear tag that might have been set by the minify task, in cases where
421
+ // the bundle name is identical to a source file
422
+ taskUtil.clearTag(sourceMap,
423
+ taskUtil.STANDARD_TAGS.OmitFromBuildResult);
424
+ }
425
+ }
426
+ const writes = [workspace.write(bundle)];
427
+ if (sourceMap) {
428
+ writes.push(workspace.write(sourceMap));
403
429
  }
404
- return workspace.write(bundle);
430
+ return Promise.all(writes);
405
431
  }
406
432
  }));
407
433
  });
@@ -1,6 +1,7 @@
1
1
  const log = require("@ui5/logger").getLogger("builder:tasks:bundlers:generateStandaloneAppBundle");
2
2
  const ReaderCollectionPrioritized = require("@ui5/fs").ReaderCollectionPrioritized;
3
3
  const moduleBundler = require("../../processors/bundlers/moduleBundler");
4
+ const createModuleNameMapping = require("./utils/createModuleNameMapping");
4
5
 
5
6
  function getBundleDefinition(config) {
6
7
  const bundleDefinition = {
@@ -88,8 +89,7 @@ module.exports = async function({workspace, dependencies, taskUtil, options: {pr
88
89
  return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.IsDebugVariant);
89
90
  });
90
91
  }
91
- const results = await combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library}");
92
- const resources = Array.prototype.concat.apply([], results);
92
+ const resources = await combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}");
93
93
 
94
94
  const isEvo = resources.find((resource) => {
95
95
  return resource.getPath() === "/resources/ui5loader.js";
@@ -101,6 +101,23 @@ module.exports = async function({workspace, dependencies, taskUtil, options: {pr
101
101
  filters = ["jquery.sap.global.js"];
102
102
  }
103
103
 
104
+ let unoptimizedModuleNameMapping;
105
+ let unoptimizedResources = resources;
106
+ if (taskUtil) {
107
+ unoptimizedResources = await new ReaderCollectionPrioritized({
108
+ name: `generateStandaloneAppBundle - prioritize workspace over dependencies: ${projectName}`,
109
+ readers: [workspace, dependencies]
110
+ }).filter(function(resource) {
111
+ // Remove any non-debug variants
112
+ return !taskUtil.getTag(resource, taskUtil.STANDARD_TAGS.HasDebugVariant);
113
+ }).byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}");
114
+
115
+ unoptimizedModuleNameMapping = createModuleNameMapping({
116
+ resources: unoptimizedResources,
117
+ taskUtil
118
+ });
119
+ }
120
+
104
121
  await Promise.all([
105
122
  moduleBundler({
106
123
  resources,
@@ -114,7 +131,7 @@ module.exports = async function({workspace, dependencies, taskUtil, options: {pr
114
131
  }
115
132
  }),
116
133
  moduleBundler({
117
- resources,
134
+ resources: unoptimizedResources,
118
135
  options: {
119
136
  bundleDefinition: getBundleDefinition({
120
137
  name: "sap-ui-custom-dbg.js",
@@ -123,16 +140,26 @@ module.exports = async function({workspace, dependencies, taskUtil, options: {pr
123
140
  }),
124
141
  bundleOptions: {
125
142
  optimize: false
126
- }
143
+ },
144
+ moduleNameMapping: unoptimizedModuleNameMapping
127
145
  }
128
146
  })
129
147
  ]).then((results) => {
130
148
  const bundles = Array.prototype.concat.apply([], results);
131
- return Promise.all(bundles.map((resource) => {
149
+ return Promise.all(bundles.map(({bundle, sourceMap}) => {
132
150
  if (taskUtil) {
133
- taskUtil.setTag(resource, taskUtil.STANDARD_TAGS.IsBundle);
151
+ taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
152
+ if (sourceMap) {
153
+ // Clear tag that might have been set by the minify task, in cases where
154
+ // the bundle name is identical to a source file
155
+ taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
156
+ }
157
+ }
158
+ const writes = [workspace.write(bundle)];
159
+ if (sourceMap) {
160
+ writes.push(workspace.write(sourceMap));
134
161
  }
135
- return workspace.write(resource);
162
+ return Promise.all(writes);
136
163
  }));
137
164
  });
138
165
  };