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

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,12 @@
1
1
  const Resource = require("./Resource");
2
2
 
3
- function extractName(path) {
4
- return path.slice( "/resources/".length);
5
- }
3
+ // function extractName(path) {
4
+ // return path.slice( "/resources/".length);
5
+ // }
6
6
 
7
7
  class LocatorResource extends Resource {
8
- constructor(pool, resource) {
9
- super(pool, extractName(resource.getPath()), null, resource.getStatInfo());
8
+ constructor(pool, resource, moduleName) {
9
+ super(pool, moduleName, null, resource.getStatInfo());
10
10
  this.resource = resource;
11
11
  }
12
12
 
@@ -17,6 +17,10 @@ class LocatorResource extends Resource {
17
17
  getProject() {
18
18
  return this.resource._project;
19
19
  }
20
+
21
+ getPath() {
22
+ return this.resource.getPath();
23
+ }
20
24
  }
21
25
 
22
26
  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
+ 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,8 @@ 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] Whether to generate a source map file for the bundle.
94
+ * Defaults to true if <code>optimize</code> is set to true
93
95
  * @property {boolean} [decorateBootstrapModule=false] If set to 'false', the module won't be decorated
94
96
  * with an optimization marker
95
97
  * @property {boolean} [addTryCatchRestartWrapper=false] Whether to wrap bootable module bundles with
@@ -101,18 +103,30 @@ const log = require("@ui5/logger").getLogger("builder:processors:bundlers:module
101
103
  */
102
104
 
103
105
  /**
104
- * Legacy preload bundler.
106
+ * Result set
107
+ *
108
+ * @public
109
+ * @typedef {object} ModuleBundlerResult
110
+ * @property {module:@ui5/fs.Resource} bundle Bundle resource
111
+ * @property {module:@ui5/fs.Resource} sourceMap Source Map
112
+ * @memberof module:@ui5/builder.processors
113
+ */
114
+
115
+ /**
116
+ * Legacy module bundler.
105
117
  *
106
118
  * @public
107
119
  * @alias module:@ui5/builder.processors.moduleBundler
108
120
  * @param {object} parameters Parameters
109
121
  * @param {module:@ui5/fs.Resource[]} parameters.resources Resources
110
122
  * @param {object} parameters.options Options
123
+ * @param {object} [parameters.options.moduleNameMapping]
124
+ Optional mapping of resource paths to module name in order to overwrite the default determination
111
125
  * @param {ModuleBundleDefinition} parameters.options.bundleDefinition Module bundle definition
112
126
  * @param {ModuleBundleOptions} [parameters.options.bundleOptions] Module bundle options
113
- * @returns {Promise<module:@ui5/fs.Resource[]>} Promise resolving with module bundle resources
127
+ * @returns {Promise<module:@ui5/builder.processors.MinifierResult[]>} 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,
@@ -134,7 +148,7 @@ module.exports = function({resources, options: {bundleDefinition, bundleOptions}
134
148
  log.verbose(`bundleOptions: ${JSON.stringify(bundleOptions, null, 2)}`);
135
149
  }
136
150
 
137
- return pool.prepare( resources ).
151
+ return pool.prepare( resources, moduleNameMapping ).
138
152
  then( () => builder.createBundle(bundleDefinition, bundleOptions) ).
139
153
  then( (results) => {
140
154
  let bundles;
@@ -146,13 +160,20 @@ module.exports = function({resources, options: {bundleDefinition, bundleOptions}
146
160
 
147
161
  return Promise.all(bundles.map((bundleObj) => {
148
162
  if ( bundleObj ) {
149
- const {name, content} = bundleObj;
163
+ const {name, content, sourceMap} = bundleObj;
150
164
  // console.log("creating bundle as '%s'", "/resources/" + name);
151
- const resource = new EvoResource({
165
+ const res = {};
166
+ res.bundle = new EvoResource({
152
167
  path: "/resources/" + name,
153
168
  string: content
154
169
  });
155
- return resource;
170
+ if (sourceMap) {
171
+ res.sourceMap = new EvoResource({
172
+ path: "/resources/" + name + ".map",
173
+ string: sourceMap
174
+ });
175
+ }
176
+ return res;
156
177
  }
157
178
  }));
158
179
  });
@@ -34,10 +34,12 @@ 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 {boolean} [parameters.addSourceMappingUrl=true]
38
+ * Whether to add a sourceMappingURL reference to the end of the minified resource
37
39
  * @returns {Promise<module:@ui5/builder.processors.MinifierResult[]>}
38
40
  * Promise resolving with object of resource, dbgResource and sourceMap
39
41
  */
40
- module.exports = async function({resources}) {
42
+ module.exports = async function({resources, addSourceMappingUrl = true}) {
41
43
  return Promise.all(resources.map(async (resource) => {
42
44
  const dbgPath = resource.getPath().replace(debugFileRegex, "-dbg$1");
43
45
  const dbgResource = await resource.clone();
@@ -46,6 +48,12 @@ module.exports = async function({resources}) {
46
48
  const filename = path.posix.basename(resource.getPath());
47
49
  const code = await resource.getString();
48
50
  try {
51
+ const sourceMapOptions = {
52
+ filename
53
+ };
54
+ if (addSourceMappingUrl) {
55
+ sourceMapOptions.url = filename + ".map";
56
+ }
49
57
  const dbgFilename = path.posix.basename(dbgPath);
50
58
  const result = await terser.minify({
51
59
  // Use debug-name since this will be referenced in the source map "sources"
@@ -63,10 +71,7 @@ module.exports = async function({resources}) {
63
71
  "sap",
64
72
  ]
65
73
  },
66
- sourceMap: {
67
- filename,
68
- url: filename + ".map"
69
- }
74
+ sourceMap: sourceMapOptions
70
75
  });
71
76
  resource.setString(result.code);
72
77
  const sourceMapResource = new Resource({
@@ -25,8 +25,53 @@ module.exports = function({
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,50 @@ module.exports = function({
34
79
  combo = combo.filter(function(resource) {
35
80
  return !taskUtil.getTag(resource, filterTag);
36
81
  });
82
+ }
37
83
 
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) {
84
+ return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}").then((resources) => {
85
+ const moduleNameMapping = {};
86
+ if (!optimize && taskUtil) {
87
+ // For "unoptimized" bundles, the non-debug files have already been filtered out above.
88
+ // Now we need to create a mapping from the debug-variant resource path to the respective module name,
89
+ // which is basically the non-debug resource path, minus the "/resources/"" prefix.
90
+ // This mapping overwrites internal logic of the LocatorResourcePool which would otherwise determine
91
+ // the module name from the resource path, which would contain "-dbg" in this case. That would be
92
+ // incorrect since debug-variants should still keep the original module name.
93
+ for (let i = resources.length - 1; i >= 0; i--) {
94
+ const resourcePath = resources[i].getPath();
43
95
  if (taskUtil.getTag(resourcePath, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
44
- const resource = await getResource();
45
- const nonDbgPath = ModuleName.getNonDebugName(resource.getPath());
96
+ const nonDbgPath = ModuleName.getNonDebugName(resourcePath);
46
97
  if (!nonDbgPath) {
47
- throw new Error(`Failed to resolve non-debug name for ${resource.getPath()}`);
98
+ throw new Error(`Failed to resolve non-debug name for ${resourcePath}`);
48
99
  }
49
- resource.setPath(nonDbgPath);
100
+ moduleNameMapping[resourcePath] = nonDbgPath.slice("/resources/".length);
50
101
  }
51
- });
102
+ }
52
103
  }
53
- }
54
-
55
- return combo.byGlob("/resources/**/*.{js,json,xml,html,properties,library}").then((resources) => {
56
104
  return moduleBundler({
57
105
  options: {
58
106
  bundleDefinition,
59
- bundleOptions
107
+ bundleOptions,
108
+ moduleNameMapping
60
109
  },
61
110
  resources
62
111
  }).then((bundles) => {
63
- return Promise.all(bundles.map((bundle) => {
112
+ return Promise.all(bundles.map(({bundle, sourceMap}) => {
64
113
  if (taskUtil) {
65
114
  taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
115
+ if (sourceMap) {
116
+ // Clear tag that might have been set by the minify task, in cases where
117
+ // the bundle name is identical to a source file
118
+ taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
119
+ }
120
+ }
121
+ const writes = [workspace.write(bundle)];
122
+ if (sourceMap) {
123
+ writes.push(workspace.write(sourceMap));
66
124
  }
67
- return workspace.write(bundle);
125
+ return Promise.all(writes);
68
126
  }));
69
127
  });
70
128
  });
@@ -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({
@@ -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
+ const unoptimizedModuleNameMapping = {};
308
315
  let unoptimizedResources = resources;
309
316
  if (taskUtil) {
310
317
  unoptimizedResources = await new ReaderCollectionPrioritized({
@@ -313,16 +320,24 @@ 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) {
323
+ }).byGlob("/**/*.{js,json,xml,html,properties,library,js.map}");
324
+
325
+ // For "unoptimized" bundles, the non-debug files have already been filtered out above.
326
+ // Now we need to create a mapping from the debug-variant resource path to the respective module
327
+ // name, which is basically the non-debug resource path, minus the "/resources/"" prefix.
328
+ // This mapping overwrites internal logic of the LocatorResourcePool which would otherwise determine
329
+ // the module name from the resource path, which would contain "-dbg" in this case. That would be
330
+ // incorrect since debug-variants should still keep the original module name.
331
+ for (let i = unoptimizedResources.length - 1; i >= 0; i--) {
332
+ const resourcePath = unoptimizedResources[i].getPath();
317
333
  if (taskUtil.getTag(resourcePath, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
318
- const resource = await getResource();
319
- const nonDbgPath = ModuleName.getNonDebugName(resource.getPath());
334
+ const nonDbgPath = ModuleName.getNonDebugName(resourcePath);
320
335
  if (!nonDbgPath) {
321
- throw new Error(`Failed to resolve non-debug name for ${resource.getPath()}`);
336
+ throw new Error(`Failed to resolve non-debug name for ${resourcePath}`);
322
337
  }
323
- resource.setPath(nonDbgPath);
338
+ unoptimizedModuleNameMapping[resourcePath] = nonDbgPath.slice("/resources/".length);
324
339
  }
325
- }).byGlob("/**/*.{js,json,xml,html,properties,library}");
340
+ }
326
341
  }
327
342
 
328
343
  let filters;
@@ -337,7 +352,10 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
337
352
  resources
338
353
  }),
339
354
  moduleBundler({
340
- options: getModuleBundlerOptions({name: "sap-ui-core-dbg.js", filters, preload: false}),
355
+ options: getModuleBundlerOptions({
356
+ name: "sap-ui-core-dbg.js", filters, preload: false,
357
+ moduleNameMapping: unoptimizedModuleNameMapping
358
+ }),
341
359
  resources: unoptimizedResources
342
360
  }),
343
361
  moduleBundler({
@@ -348,17 +366,27 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
348
366
  }),
349
367
  moduleBundler({
350
368
  options: getModuleBundlerOptions({
351
- name: "sap-ui-core-nojQuery-dbg.js", filters, preload: false, provided: true
369
+ name: "sap-ui-core-nojQuery-dbg.js", filters, preload: false, provided: true,
370
+ moduleNameMapping: unoptimizedModuleNameMapping
352
371
  }),
353
372
  resources: unoptimizedResources
354
373
  }),
355
374
  ]).then((results) => {
356
375
  const bundles = Array.prototype.concat.apply([], results);
357
- return Promise.all(bundles.map((bundle) => {
376
+ return Promise.all(bundles.map(({bundle, sourceMap}) => {
358
377
  if (taskUtil) {
359
378
  taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
379
+ if (sourceMap) {
380
+ // Clear tag that might have been set by the minify task, in cases where
381
+ // the bundle name is identical to a source file
382
+ taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
383
+ }
360
384
  }
361
- return workspace.write(bundle);
385
+ const writes = [workspace.write(bundle)];
386
+ if (sourceMap) {
387
+ writes.push(workspace.write(sourceMap));
388
+ }
389
+ return Promise.all(writes);
362
390
  }));
363
391
  });
364
392
  }
@@ -396,12 +424,22 @@ module.exports = function({workspace, dependencies, taskUtil, options: {projectN
396
424
  return createLibraryBundles(libraryNamespace, resources, excludes)
397
425
  .then((results) => {
398
426
  const bundles = Array.prototype.concat.apply([], results);
399
- return Promise.all(bundles.map((bundle) => {
427
+ return Promise.all(bundles.map(({bundle, sourceMap} = {}) => {
400
428
  if (bundle) {
401
429
  if (taskUtil) {
402
430
  taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
431
+ if (sourceMap) {
432
+ // Clear tag that might have been set by the minify task, in cases where
433
+ // the bundle name is identical to a source file
434
+ taskUtil.clearTag(sourceMap,
435
+ taskUtil.STANDARD_TAGS.OmitFromBuildResult);
436
+ }
437
+ }
438
+ const writes = [workspace.write(bundle)];
439
+ if (sourceMap) {
440
+ writes.push(workspace.write(sourceMap));
403
441
  }
404
- return workspace.write(bundle);
442
+ return Promise.all(writes);
405
443
  }
406
444
  }));
407
445
  });
@@ -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 ModuleName = require("../../lbt/utils/ModuleName");
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,35 @@ module.exports = async function({workspace, dependencies, taskUtil, options: {pr
101
101
  filters = ["jquery.sap.global.js"];
102
102
  }
103
103
 
104
+ const 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
+ // For "unoptimized" bundles, the non-debug files have already been filtered out above.
116
+ // Now we need to create a mapping from the debug-variant resource path to the respective module name,
117
+ // which is basically the non-debug resource path, minus the "/resources/"" prefix.
118
+ // This mapping overwrites internal logic of the LocatorResourcePool which would otherwise determine
119
+ // the module name from the resource path, which would contain "-dbg" in this case. That would be
120
+ // incorrect since debug-variants should still keep the original module name.
121
+ for (let i = unoptimizedResources.length - 1; i >= 0; i--) {
122
+ const resourcePath = unoptimizedResources[i].getPath();
123
+ if (taskUtil.getTag(resourcePath, taskUtil.STANDARD_TAGS.IsDebugVariant)) {
124
+ const nonDbgPath = ModuleName.getNonDebugName(resourcePath);
125
+ if (!nonDbgPath) {
126
+ throw new Error(`Failed to resolve non-debug name for ${resourcePath}`);
127
+ }
128
+ unoptimizedModuleNameMapping[resourcePath] = nonDbgPath.slice("/resources/".length);
129
+ }
130
+ }
131
+ }
132
+
104
133
  await Promise.all([
105
134
  moduleBundler({
106
135
  resources,
@@ -114,7 +143,7 @@ module.exports = async function({workspace, dependencies, taskUtil, options: {pr
114
143
  }
115
144
  }),
116
145
  moduleBundler({
117
- resources,
146
+ resources: unoptimizedResources,
118
147
  options: {
119
148
  bundleDefinition: getBundleDefinition({
120
149
  name: "sap-ui-custom-dbg.js",
@@ -123,16 +152,26 @@ module.exports = async function({workspace, dependencies, taskUtil, options: {pr
123
152
  }),
124
153
  bundleOptions: {
125
154
  optimize: false
126
- }
155
+ },
156
+ moduleNameMapping: unoptimizedModuleNameMapping
127
157
  }
128
158
  })
129
159
  ]).then((results) => {
130
160
  const bundles = Array.prototype.concat.apply([], results);
131
- return Promise.all(bundles.map((resource) => {
161
+ return Promise.all(bundles.map(({bundle, sourceMap}) => {
132
162
  if (taskUtil) {
133
- taskUtil.setTag(resource, taskUtil.STANDARD_TAGS.IsBundle);
163
+ taskUtil.setTag(bundle, taskUtil.STANDARD_TAGS.IsBundle);
164
+ if (sourceMap) {
165
+ // Clear tag that might have been set by the minify task, in cases where
166
+ // the bundle name is identical to a source file
167
+ taskUtil.clearTag(sourceMap, taskUtil.STANDARD_TAGS.OmitFromBuildResult);
168
+ }
169
+ }
170
+ const writes = [workspace.write(bundle)];
171
+ if (sourceMap) {
172
+ writes.push(workspace.write(sourceMap));
134
173
  }
135
- return workspace.write(resource);
174
+ return Promise.all(writes);
136
175
  }));
137
176
  });
138
177
  };
@@ -105,7 +105,7 @@ function getCreatorOptions(projectName) {
105
105
  module.exports = async function({workspace, dependencies, taskUtil, options: {projectName}}) {
106
106
  let resources = await workspace.byGlob(["/resources/**/*"].concat(DEFAULT_EXCLUDES));
107
107
  let dependencyResources =
108
- await dependencies.byGlob("/resources/**/*.{js,json,xml,html,properties,library}");
108
+ await dependencies.byGlob("/resources/**/*.{js,json,xml,html,properties,library,js.map}");
109
109
 
110
110
  if (taskUtil) {
111
111
  // Filter out resources that will be omitted from the build results