Skip to content

Commit

Permalink
Fix infinite recursion for dependency cycles
Browse files Browse the repository at this point in the history
  • Loading branch information
mbeckem committed Sep 12, 2023
1 parent 1da64e5 commit de95243
Show file tree
Hide file tree
Showing 15 changed files with 100 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/chatty-ligers-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@open-pioneer/vite-plugin-pioneer": patch
---

Fix infinite recursion when packages depend on each other (dependency cycle).
20 changes: 20 additions & 0 deletions packages/vite-plugin/src/codegenPlugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,26 @@ describe("codegen support", function () {
expect(error.message).toMatch(/[email protected] at/);
expect(error.message).toMatch(/[email protected] at/);
});

it("supports dependency cycles", async function () {
// The important thing about this test is that it terminates!
// Dependency cycle:
// test-app --> a --> b --> a
const rootDir = resolve(TEST_DATA_DIR, "codegen-packages-cycle");
const outDir = resolve(TEMP_DATA_DIR, "codegen-packages-cycle");

await runViteBuild({
outDir,
rootDir,
pluginOptions: {
apps: ["test-app"]
}
});

const appJs = readFileSync(join(outDir, "test-app.js"), "utf-8");
assert.include(appJs, `console.info("Service A");`);
assert.include(appJs, `console.info("Service B");`);
});
});

function findModuleContaining(dir: string, needle: string) {
Expand Down
20 changes: 16 additions & 4 deletions packages/vite-plugin/src/metadata/MetadataRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ export class MetadataRepository {

// Map to ensure that we don't return duplicates. Key: package name
const packageMetadataByName = new Map<string, PackageMetadata>();
const packageSeenByDirectory = new Set<string>();
packageMetadataByName.set(appPackageMetadata.name, appPackageMetadata);
packageSeenByDirectory.add(appPackageMetadata.directory);

// Recursively visit all dependencies.
// Detected metadata is placed into `packageMetadata`.
Expand All @@ -123,14 +125,24 @@ export class MetadataRepository {
dependency,
importedFrom
});
if (packageMetadata) {
if (!packageMetadataByName.has(packageMetadata.name)) {
packageMetadataByName.set(packageMetadata.name, packageMetadata);
}
if (!packageMetadata) {
return;
}

if (!packageMetadataByName.has(packageMetadata.name)) {
packageMetadataByName.set(packageMetadata.name, packageMetadata);
}

if (!packageSeenByDirectory.has(packageMetadata.directory)) {
packageSeenByDirectory.add(packageMetadata.directory);

await visitDependencies(
packageMetadata.dependencies,
packageMetadata.packageJsonPath
);
} else {
isDebug &&
debug(`Skipping already visited package at %s`, packageMetadata.directory);
}
});
return await Promise.all(jobs);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import { packages } from "open-pioneer:app";
console.log(packages);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default {};

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "test-app",
"private": true,
"dependencies": {
"a": "1.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default {
services: {
Service: {
provides: [
{
name: "a.Service"
}
]
}
},
};

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "a",
"version": "1.0.0",
"dependencies": {
"b": "1.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class Service {
constructor() {
console.info("Service A");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default {
services: {
Service: {
provides: [
{
name: "b.Service"
}
]
}
},
};

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "b",
"version": "1.0.0",
"dependencies": {
"a": "1.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class Service {
constructor() {
console.info("Service B");
}
}

0 comments on commit de95243

Please sign in to comment.