Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] generateResourcesJson: Analyze debug bundles #669

Merged
merged 3 commits into from
Jan 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 33 additions & 15 deletions lib/lbt/resources/ResourceCollector.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,17 +193,16 @@ class ResourceCollector {
}

async determineResourceDetails({
debugResources, mergedResources, designtimeResources, supportResources, debugBundles
debugResources, mergedResources, designtimeResources, supportResources
}) {
const baseNames = new Set();
const debugFilter = new ResourceFilterList(debugResources);
const mergeFilter = new ResourceFilterList(mergedResources);
const designtimeFilter = new ResourceFilterList(designtimeResources);
const supportFilter = new ResourceFilterList(supportResources);
const debugBundleFilter = new ResourceFilterList(debugBundles);

const promises = [];
const nonBundledDebugResources = [];
const debugResourcesInfo = [];

for (const [name, info] of this._resources.entries()) {
if ( debugFilter.matches(name) ) {
Expand Down Expand Up @@ -231,13 +230,14 @@ class ResourceCollector {
}

if ( /(?:\.js|\.view\.xml|\.control\.xml|\.fragment\.xml)$/.test(name) ) {
if ( (!info.isDebug || debugBundleFilter.matches(name)) ) {
// Only analyze non-debug files and special debug bundles (like sap-ui-core-dbg.js)
if ( !info.isDebug ) {
// Only analyze non-dbg files in first run
promises.push(
this.enrichWithDependencyInfo(info)
);
} else {
nonBundledDebugResources.push(info);
// Collect dbg files to be handled in a second step (see below)
debugResourcesInfo.push(info);
}
}

Expand Down Expand Up @@ -279,19 +279,37 @@ class ResourceCollector {

await Promise.all(promises);

for (let i = nonBundledDebugResources.length - 1; i >= 0; i--) {
const dbgInfo = nonBundledDebugResources[i];
const debugBundlePromises = [];

for (let i = debugResourcesInfo.length - 1; i >= 0; i--) {
const dbgInfo = debugResourcesInfo[i];
const nonDebugName = ResourceInfoList.getNonDebugName(dbgInfo.name);
const nonDbgInfo = this._resources.get(nonDebugName);
const newDbgInfo = new ResourceInfo(dbgInfo.name);

// First copy info of analysis from non-dbg file (included, required, condRequired, ...)
newDbgInfo.copyFrom(null, nonDbgInfo);
// Then copy over info from dbg file to properly set name, isDebug, etc.
newDbgInfo.copyFrom(null, dbgInfo);

this._resources.set(dbgInfo.name, newDbgInfo);
// FIXME: "merged" property is only calculated in ResourceInfo#copyFrom
// Therefore using the same logic here to compute it.
if (!nonDbgInfo || (nonDbgInfo.included != null && nonDbgInfo.included.size > 0)) {
// We need to analyze the dbg resource if there is no non-dbg variant or
// it is a bundle because we will (usually) have different content.
debugBundlePromises.push(
this.enrichWithDependencyInfo(dbgInfo)
);
} else {
// If the non-dbg resource is not a bundle, we can just copy over the info and skip
// analyzing the dbg variant as both should have the same info.

const newDbgInfo = new ResourceInfo(dbgInfo.name);

// First copy info of analysis from non-dbg file (included, required, condRequired, ...)
newDbgInfo.copyFrom(null, nonDbgInfo);
// Then copy over info from dbg file to properly set name, isDebug, etc.
newDbgInfo.copyFrom(null, dbgInfo);

this._resources.set(dbgInfo.name, newDbgInfo);
}
}

await Promise.all(debugBundlePromises);
}

createOrphanFilters() {
Expand Down
18 changes: 2 additions & 16 deletions lib/processors/resourceListCreator.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,6 @@ const DEFAULT_SUPPORT_RESOURCES_FILTER = [
"**/*.support.js"
];

/**
* Hard coded debug bundle, to trigger separate analysis for this filename
* because sap-ui-core.js and sap-ui-core-dbg.js have different includes
*
* @type {string[]}
*/
const DEBUG_BUNDLES = [
"sap-ui-core-dbg.js",
"sap-ui-core-nojQuery-dbg.js"
];

/**
* Creates and adds resources.json entry (itself) to the list.
*
Expand Down Expand Up @@ -138,8 +127,7 @@ module.exports = async function({resources, dependencyResources = [], options})
debugResources: DEFAULT_DEBUG_RESOURCES_FILTER,
mergedResources: DEFAULT_BUNDLE_RESOURCES_FILTER,
designtimeResources: DEFAULT_DESIGNTIME_RESOURCES_FILTER,
supportResources: DEFAULT_SUPPORT_RESOURCES_FILTER,
debugBundles: DEBUG_BUNDLES
supportResources: DEFAULT_SUPPORT_RESOURCES_FILTER
}, options);

const pool = new LocatorResourcePool();
Expand All @@ -158,12 +146,10 @@ module.exports = async function({resources, dependencyResources = [], options})
}

await collector.determineResourceDetails({
pool,
debugResources: options.debugResources,
mergedResources: options.mergedResources,
designtimeResources: options.designtimeResources,
supportResources: options.supportResources,
debugBundles: options.debugBundles
supportResources: options.supportResources
});

// group resources by components and create ResourceInfoLists
Expand Down
54 changes: 44 additions & 10 deletions test/lib/lbt/resources/ResourceCollector.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ test.serial("visitResource: ensure proper matching of indicator files", async (t
t.is(resourceCollector.components.size, 0, "No prefixes should be added");
});

test.serial("groupResourcesByComponents: debugBundles", async (t) => {
test.serial("groupResourcesByComponents: external resources", async (t) => {
const resourceCollector = new ResourceCollector();
resourceCollector.setExternalResources({
"testcomp": ["my/file.js"]
Expand Down Expand Up @@ -149,25 +149,60 @@ test.serial("determineResourceDetails: view.xml", async (t) => {
t.is(enrichWithDependencyInfoStub.getCall(0).args[0].name, "mylib/my.view.xml", "is called with view");
});

test.serial("determineResourceDetails: Debug bundle", async (t) => {
test.serial("determineResourceDetails: Debug bundle (without non-debug variant)", async (t) => {
const resourceCollector = new ResourceCollector();

const enrichWithDependencyInfoStub = sinon.stub(resourceCollector, "enrichWithDependencyInfo").resolves();
await resourceCollector.visitResource({getPath: () => "/resources/MyBundle-dbg.js", getSize: async () => 13});

await resourceCollector.determineResourceDetails({
debugBundles: ["MyBundle-dbg.js"]
debugResources: ["**/*-dbg.js"], // MyBundle-dbg.js should be marked as "isDebug"
});

t.is(enrichWithDependencyInfoStub.callCount, 1, "enrichWithDependencyInfo is called once");
t.is(enrichWithDependencyInfoStub.getCall(0).args[0].name, "MyBundle-dbg.js",
"enrichWithDependencyInfo is called with debug bundle");
});

test.serial("determineResourceDetails: Debug bundle (with non-debug variant)", async (t) => {
const resourceCollector = new ResourceCollector();

const enrichWithDependencyInfoStub = sinon.stub(resourceCollector, "enrichWithDependencyInfo")
.onFirstCall().callsFake(async (resourceInfo) => {
resourceInfo.included = new Set(["SomeModule.js"]);
resourceInfo.required = new Set(["Boot.js"]);
})
.onSecondCall().callsFake(async (resourceInfo) => {
resourceInfo.required = new Set(["Boot.js"]);
});
await resourceCollector.visitResource({getPath: () => "/resources/MyBundle-dbg.js", getSize: async () => 13});
await resourceCollector.visitResource({getPath: () => "/resources/MyBundle.js", getSize: async () => 13});

await resourceCollector.determineResourceDetails({
debugResources: ["**/*-dbg.js"], // MyBundle-dbg.js should be marked as "isDebug"
});
t.is(enrichWithDependencyInfoStub.callCount, 2, "enrichWithDependencyInfo is called twice");
t.is(enrichWithDependencyInfoStub.getCall(0).args[0].name, "MyBundle.js",
"enrichWithDependencyInfo is called with non-debug bundle first");
t.is(enrichWithDependencyInfoStub.getCall(1).args[0].name, "MyBundle-dbg.js",
"enrichWithDependencyInfo is called with debug bundle on second run");

const bundleInfo = resourceCollector._resources.get("MyBundle.js");
t.deepEqual(bundleInfo.included, new Set(["SomeModule.js"]));
t.deepEqual(bundleInfo.required, new Set(["Boot.js"]));
t.is(bundleInfo.isDebug, false);

const debugBundleInfo = resourceCollector._resources.get("MyBundle-dbg.js");
t.is(debugBundleInfo.included, null);
t.deepEqual(debugBundleInfo.required, new Set(["Boot.js"]));
t.is(debugBundleInfo.isDebug, true);
});

test.serial("determineResourceDetails: Debug files and non-debug files", async (t) => {
const resourceCollector = new ResourceCollector();

const enrichWithDependencyInfoStub = sinon.stub(resourceCollector, "enrichWithDependencyInfo")
.callsFake((resourceInfo) => {
.callsFake(async (resourceInfo) => {
// Simulate enriching resource info with dependency info to test whether it gets shared
// with the dbg resource later on
resourceInfo.dynRequired = true;
Expand All @@ -183,16 +218,15 @@ test.serial("determineResourceDetails: Debug files and non-debug files", async (
}));

await resourceCollector.determineResourceDetails({
debugResources: ["**/*-dbg.js"],
debugBundles: ["MyBundle-dbg.js"]
debugResources: ["**/*-dbg.js"]
});
t.is(enrichWithDependencyInfoStub.callCount, 3, "enrichWithDependencyInfo is called three times");
t.is(enrichWithDependencyInfoStub.getCall(0).args[0].name, "MyBundle-dbg.js",
"enrichWithDependencyInfo called with debug bundle");
t.is(enrichWithDependencyInfoStub.getCall(1).args[0].name, "mylib/MyControlA.js",
t.is(enrichWithDependencyInfoStub.getCall(0).args[0].name, "mylib/MyControlA.js",
"enrichWithDependencyInfo called with non-debug control A");
t.is(enrichWithDependencyInfoStub.getCall(2).args[0].name, "mylib/MyControlB.js",
t.is(enrichWithDependencyInfoStub.getCall(1).args[0].name, "mylib/MyControlB.js",
"enrichWithDependencyInfo called with non-debug control B");
t.is(enrichWithDependencyInfoStub.getCall(2).args[0].name, "MyBundle-dbg.js",
"enrichWithDependencyInfo called with debug bundle");

t.is(resourceCollector._resources.get("MyBundle-dbg.js").isDebug, true, "MyBundle-dbg is a debug file");
t.is(resourceCollector._resources.get("MyBundle-dbg.js").dynRequired, true,
Expand Down