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

[WIP] Rework sourcefile analysis strategy #253

Closed
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
42 changes: 38 additions & 4 deletions src/AstAnalyser.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,14 @@ export class AstAnalyser {
* @constructor
* @param { SourceParser } [parser]
*/
constructor(parser = new JsSourceParser()) {
constructor(parser = new JsSourceParser(), entryFiles = []) {
this.parser = parser;
this.analyzedFiles = new Map();
this.entryFiles = entryFiles.map((entry) => path.resolve(entry));
}

reset() {
this.analyzedFiles = new Map();
}

analyse(str, options = Object.create(null)) {
Expand Down Expand Up @@ -59,6 +65,18 @@ export class AstAnalyser {
pathToFile,
options = {}
) {
const filePath = pathToFile instanceof URL ? pathToFile.href.replace(/^file:\/\//, "") : pathToFile;
const filePathString = path.resolve(filePath);

if (this.analyzedFiles.has(filePathString)) {
return this.analyzedFiles.get(filePathString);
}

const toSkip = this.#toSkip(filePathString);
if (toSkip) {
return { ok: true, isSkipped: true };
}

try {
const {
packageName = null,
Expand All @@ -67,8 +85,6 @@ export class AstAnalyser {
} = options;

const str = await fs.readFile(pathToFile, "utf-8");
const filePathString = pathToFile instanceof URL ? pathToFile.href : pathToFile;

const isMin = filePathString.includes(".min") || isMinified(str);
const data = this.analyse(str, {
isMinified: isMin,
Expand All @@ -80,12 +96,16 @@ export class AstAnalyser {
data.dependencies.delete(packageName);
}

return {
const report = {
ok: true,
dependencies: data.dependencies,
warnings: data.warnings,
isMinified: !data.isOneLineRequire && isMin
};

this.analyzedFiles.set(filePathString, report);

return report;
}
catch (error) {
return {
Expand Down Expand Up @@ -127,4 +147,18 @@ export class AstAnalyser {
#removeHTMLComment(str) {
return str.replaceAll(/<!--[\s\S]*?(?:-->)/g, "");
}

#toSkip(filePathString) {
if (!this.entryFiles.length) {
return false;
}

for (const dir of this.entryFiles) {
if (filePathString.startsWith(dir)) {
return false;
}
}

return true;
}
}
76 changes: 76 additions & 0 deletions test/AstAnalyser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,82 @@ describe("AstAnalyser", (t) => {
);
});

it("should not analyze the same file twice", async(t) => {
const analyser = new AstAnalyser(new JsSourceParser());

t.mock.method(AstAnalyser.prototype, "analyse");

const result1 = await analyser.analyseFile(
new URL("depName.js", FIXTURE_URL),
{ module: false, packageName: "foobar" }
);

const result2 = await analyser.analyseFile(
new URL("depName.js", FIXTURE_URL),
{ module: false, packageName: "foobar" }
);

const result3 = await analyser.analyseFile(
"test/fixtures/searchRuntimeDependencies/depName.js",
{ module: false, packageName: "foobar" }
);

assert.equal(result1, result2);
assert.equal(result2, result3);

let calls = AstAnalyser.prototype.analyse.mock.calls;
assert.strictEqual(calls.length, 1);

// should remove the cache
analyser.reset();

await analyser.analyseFile(
"test/fixtures/searchRuntimeDependencies/depName.js",
{ module: false, packageName: "foobar" }
);

calls = AstAnalyser.prototype.analyse.mock.calls;
assert.strictEqual(calls.length, 2);
});

it("should skip files that are not part of entry files", async(t) => {
const FIXTURE_URL = new URL("fixtures/entryFiles/", import.meta.url);

const analyser = new AstAnalyser(new JsSourceParser(), [
"test/fixtures/entryFiles/src",
"test/fixtures/entryFiles/src2"
]);

const validTestFiles = [
"src/foo.js",
"src/bar/bar.js",
"src2/foo.js",
"src2/bar/bar.js"
];

validTestFiles.forEach(async(file) => {
const result = await analyser.analyseFile(
new URL(file, FIXTURE_URL)
);

assert.ok(result.ok);
});

const invalidTestFiles = [
"test/foo.js",
"test/bar/bar.js"
];

invalidTestFiles.forEach(async(file) => {
const result = await analyser.analyseFile(
new URL(file, FIXTURE_URL)
);

assert.ok(result.ok);
assert.ok(result.isSkipped);
});
});

it("should fail with a parsing error", async() => {
const result = await getAnalyser().analyseFile(
new URL("parsingError.js", FIXTURE_URL),
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/entryFiles/src/bar/bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require("foobar");
1 change: 1 addition & 0 deletions test/fixtures/entryFiles/src/foo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require("foobar");
1 change: 1 addition & 0 deletions test/fixtures/entryFiles/src2/bar/bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require("foobar");
1 change: 1 addition & 0 deletions test/fixtures/entryFiles/src2/foo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require("foobar");
1 change: 1 addition & 0 deletions test/fixtures/entryFiles/test/bar/bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require("foobar");
1 change: 1 addition & 0 deletions test/fixtures/entryFiles/test/foo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require("foobar");
Loading