mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 09:39:25 +00:00
fix(tooling): detect imports following regular expressions (#137804)
This commit is contained in:
parent
06c7cec68a
commit
daa5cba0cd
3 changed files with 41 additions and 20 deletions
|
|
@ -103,18 +103,14 @@ export function writeLine(stream, text) {
|
|||
}
|
||||
|
||||
function hasSupplementalModuleReference(ts, source, acceptSpecifier) {
|
||||
const checkUrl = source.includes("new") && source.includes("import") && source.includes("meta");
|
||||
const interpolationStart = source.indexOf("${");
|
||||
const checkRequire =
|
||||
interpolationStart >= 0 &&
|
||||
(source.includes("require") || source.indexOf("\\u", interpolationStart + 2) >= 0);
|
||||
const interpolatedSlash =
|
||||
interpolationStart < 0 ? -1 : source.indexOf("/", interpolationStart + 2);
|
||||
const checkTemplateImport =
|
||||
interpolatedSlash >= 0 && source.indexOf("import", interpolatedSlash + 1) >= 0;
|
||||
const checkNamespaceExport =
|
||||
source.includes("export") && source.includes("*") && source.includes("as");
|
||||
if (!checkUrl && !checkRequire && !checkTemplateImport && !checkNamespaceExport) {
|
||||
// Escaped names and regexp ambiguity must reach the scanner before rejecting the file.
|
||||
if (
|
||||
!source.includes("new") &&
|
||||
!source.includes("${") &&
|
||||
!source.includes("export") &&
|
||||
!source.includes("/") &&
|
||||
!source.includes("\\u")
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -136,7 +132,6 @@ function hasSupplementalModuleReference(ts, source, acceptSpecifier) {
|
|||
|
||||
for (let token = scanner.scan(); token !== kinds.EndOfFileToken; token = scanner.scan()) {
|
||||
if (
|
||||
checkUrl &&
|
||||
token === kinds.NewKeyword &&
|
||||
scanner.lookAhead(
|
||||
() =>
|
||||
|
|
@ -149,7 +144,6 @@ function hasSupplementalModuleReference(ts, source, acceptSpecifier) {
|
|||
return true;
|
||||
}
|
||||
if (
|
||||
checkRequire &&
|
||||
(token === kinds.RequireKeyword ||
|
||||
(token === kinds.Identifier && scanner.getTokenValue() === "require")) &&
|
||||
scanner.lookAhead(() => scanner.scan() === kinds.OpenParenToken && scanAcceptedSpecifier())
|
||||
|
|
@ -157,7 +151,6 @@ function hasSupplementalModuleReference(ts, source, acceptSpecifier) {
|
|||
return true;
|
||||
}
|
||||
if (
|
||||
checkNamespaceExport &&
|
||||
token === kinds.ExportKeyword &&
|
||||
scanner.lookAhead(() => {
|
||||
let next = scanner.scan();
|
||||
|
|
@ -170,11 +163,9 @@ function hasSupplementalModuleReference(ts, source, acceptSpecifier) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// A context-free slash may start a regexp whose `}` would corrupt interpolation tracking.
|
||||
if (
|
||||
templateBraceDepths.length > 0 &&
|
||||
(token === kinds.SlashToken || token === kinds.SlashEqualsToken)
|
||||
) {
|
||||
// Only the parser distinguishes division from regexps, whose quotes or braces
|
||||
// can hide later module references from a context-free scanner.
|
||||
if (token === kinds.SlashToken || token === kinds.SlashEqualsToken) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@ describe("architecture boundary module reference scanner", () => {
|
|||
});
|
||||
|
||||
it.each([
|
||||
'const pattern = /"/; import "../../src/allowed.js";',
|
||||
'new URL("../../src/allowed.js", import.m\\u0065ta.url)',
|
||||
'const message = `${(24 / 2) ? require("../../src/allowed.js") : null}`',
|
||||
'const message = `${/}/.test("safe") ? require("../../src/allowed.js") : null}`',
|
||||
'const message = `${\\u0072equire("../../src/allowed.js")}`',
|
||||
|
|
@ -193,6 +195,16 @@ describe("architecture boundary module reference scanner", () => {
|
|||
).toEqual([{ kind: "import", line: 3, specifier: forbiddenPath }]);
|
||||
});
|
||||
|
||||
it("sorts references on the same line by kind and specifier", () => {
|
||||
expect(
|
||||
collectModuleReferencesFromSource('import "./z.js"; require("./z.js"); import "./a.js";'),
|
||||
).toEqual([
|
||||
{ kind: "commonjs-require", line: 1, specifier: "./z.js" },
|
||||
{ kind: "import", line: 1, specifier: "./a.js" },
|
||||
{ kind: "import", line: 1, specifier: "./z.js" },
|
||||
]);
|
||||
});
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: "import.meta URL",
|
||||
|
|
|
|||
|
|
@ -95,12 +95,30 @@ describe("extension import boundary checker", () => {
|
|||
createSource: (specifier: string) => "require(" + JSON.stringify(specifier) + ")",
|
||||
kind: "commonjs-require",
|
||||
},
|
||||
{
|
||||
name: "import after a quote-containing regexp",
|
||||
createSource: (specifier: string) =>
|
||||
'const pattern = /"/; import ' + JSON.stringify(specifier),
|
||||
kind: "import",
|
||||
},
|
||||
{
|
||||
name: "CommonJS require after a quote-containing regexp",
|
||||
createSource: (specifier: string) =>
|
||||
'const pattern = /"/; require(' + JSON.stringify(specifier) + ")",
|
||||
kind: "commonjs-require",
|
||||
},
|
||||
{
|
||||
name: "import.meta URL",
|
||||
createSource: (specifier: string) =>
|
||||
"new URL(" + JSON.stringify(specifier) + ", import.meta.url)",
|
||||
kind: "import-meta-url",
|
||||
},
|
||||
{
|
||||
name: "import.meta URL with an escaped meta property",
|
||||
createSource: (specifier: string) =>
|
||||
"new URL(" + JSON.stringify(specifier) + ", import.m\\u0065ta.url)",
|
||||
kind: "import-meta-url",
|
||||
},
|
||||
{
|
||||
name: "comment-obscured namespace export",
|
||||
createSource: (specifier: string) =>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue