From bdded79bb37b3b1a43e25d881cd059f74ddde8a8 Mon Sep 17 00:00:00 2001 From: tesseractjh Date: Sun, 30 Nov 2025 01:09:33 +0900 Subject: [PATCH 1/3] Add use cache directives --- javascript/ql/lib/semmle/javascript/Stmt.qll | 15 +++++++++++++++ .../Directives/KnownDirective.expected | 15 +++++++++++++-- .../ql/test/library-tests/Directives/tst.js | 11 +++++++++++ .../UnknownDirective/UnknownDirective.expected | 8 ++++---- .../UnknownDirective/UnknownDirective.js | 3 +++ 5 files changed, 46 insertions(+), 6 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/Stmt.qll b/javascript/ql/lib/semmle/javascript/Stmt.qll index f97b07ac8e94..453bc4076220 100644 --- a/javascript/ql/lib/semmle/javascript/Stmt.qll +++ b/javascript/ql/lib/semmle/javascript/Stmt.qll @@ -434,6 +434,21 @@ module Directive { class UseClientDirective extends KnownDirective { UseClientDirective() { this.getDirectiveText() = "use client" } } + + /** + * A `use cache` directive. + * + * Examples: + * + * ``` + * "use cache"; + * "use cache: remote"; + * "use cache: private"; + * ``` + */ + class UseCacheDirective extends KnownDirective { + UseCacheDirective() { this.getDirectiveText().regexpMatch("use cache(: (remote|private))?") } + } } /** diff --git a/javascript/ql/test/library-tests/Directives/KnownDirective.expected b/javascript/ql/test/library-tests/Directives/KnownDirective.expected index 3803ff3ced67..731158e7e8fb 100644 --- a/javascript/ql/test/library-tests/Directives/KnownDirective.expected +++ b/javascript/ql/test/library-tests/Directives/KnownDirective.expected @@ -1,5 +1,16 @@ | tst.js:1:1:1:13 | 'use strict'; | use strict | | tst.js:2:1:2:10 | 'use asm'; | use asm | | tst.js:3:1:3:9 | 'bundle'; | bundle | -| tst.js:12:3:12:12 | 'use asm'; | use asm | -| tst.js:19:5:19:17 | 'use strict'; | use strict | +| tst.js:4:1:4:13 | 'use server'; | use server | +| tst.js:5:1:5:13 | 'use client'; | use client | +| tst.js:6:1:6:12 | 'use cache'; | use cache | +| tst.js:7:1:7:20 | 'use cache: remote'; | use cache: remote | +| tst.js:8:1:8:21 | 'use ca ... ivate'; | use cache: private | +| tst.js:17:3:17:12 | 'use asm'; | use asm | +| tst.js:18:3:18:11 | 'bundle'; | bundle | +| tst.js:19:3:19:15 | 'use server'; | use server | +| tst.js:20:3:20:15 | 'use client'; | use client | +| tst.js:21:3:21:14 | 'use cache'; | use cache | +| tst.js:22:3:22:22 | 'use cache: remote'; | use cache: remote | +| tst.js:23:3:23:23 | 'use ca ... ivate'; | use cache: private | +| tst.js:30:5:30:17 | 'use strict'; | use strict | diff --git a/javascript/ql/test/library-tests/Directives/tst.js b/javascript/ql/test/library-tests/Directives/tst.js index 2bf9020ae6f4..ec03cbffa0e5 100644 --- a/javascript/ql/test/library-tests/Directives/tst.js +++ b/javascript/ql/test/library-tests/Directives/tst.js @@ -1,6 +1,11 @@ 'use strict'; // this is a directive 'use asm'; // and so is this 'bundle';// and this +'use server'; +'use client'; +'use cache'; +'use cache: remote'; +'use cache: private'; { 'use strict'; // but this isn't a directive } @@ -10,6 +15,12 @@ function f() { 'use\x20strict'; // this is a directive, though not a strict mode directive 'use asm'; // and so is this + 'bundle'; + 'use server'; + 'use client'; + 'use cache'; + 'use cache: remote'; + 'use cache: private'; ; 'use strict'; // but this isn't a directive } diff --git a/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.expected b/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.expected index 87922ff82a24..4d089fdba5be 100644 --- a/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.expected +++ b/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.expected @@ -11,7 +11,7 @@ | UnknownDirective.js:12:5:12:17 | "use struct;" | Unknown directive: 'use struct;'. | | UnknownDirective.js:13:5:13:17 | "Use Strict"; | Unknown directive: 'Use Strict'. | | UnknownDirective.js:14:5:14:14 | "use bar"; | Unknown directive: 'use bar'. | -| UnknownDirective.js:40:5:40:17 | "[0, 0, 0];"; | Unknown directive: '[0, 0, 0];'. | -| UnknownDirective.js:41:5:41:65 | "[0, 0, ... , 0];"; | Unknown directive: '[0, 0, 0, 0, 0, 0, 0 ... (truncated)'. | -| UnknownDirective.js:47:5:47:15 | ":nomunge"; | Unknown directive: ':nomunge'. | -| UnknownDirective.js:48:5:48:30 | "foo(), ... munge"; | Unknown directive: 'foo(), bar, baz:nomu ... (truncated)'. | +| UnknownDirective.js:43:5:43:17 | "[0, 0, 0];"; | Unknown directive: '[0, 0, 0];'. | +| UnknownDirective.js:44:5:44:65 | "[0, 0, ... , 0];"; | Unknown directive: '[0, 0, 0, 0, 0, 0, 0 ... (truncated)'. | +| UnknownDirective.js:50:5:50:15 | ":nomunge"; | Unknown directive: ':nomunge'. | +| UnknownDirective.js:51:5:51:30 | "foo(), ... munge"; | Unknown directive: 'foo(), bar, baz:nomu ... (truncated)'. | diff --git a/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.js b/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.js index e86b7b9d95bc..78c0d79f2c1a 100644 --- a/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.js +++ b/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.js @@ -34,6 +34,9 @@ function good() { "deps bar"; "use server"; "use client"; + "use cache"; + "use cache: remote"; + "use cache: private"; } function data() { From 7d32876a44ed0b85b40dfe003862318c566a5ca6 Mon Sep 17 00:00:00 2001 From: tesseractjh Date: Sun, 30 Nov 2025 13:54:12 +0900 Subject: [PATCH 2/3] change note --- .../ql/lib/change-notes/2025-11-30-use-cache-directives.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 javascript/ql/lib/change-notes/2025-11-30-use-cache-directives.md diff --git a/javascript/ql/lib/change-notes/2025-11-30-use-cache-directives.md b/javascript/ql/lib/change-notes/2025-11-30-use-cache-directives.md new file mode 100644 index 000000000000..6a8edce26d1e --- /dev/null +++ b/javascript/ql/lib/change-notes/2025-11-30-use-cache-directives.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- + +- Support `use cache` directives for Next.js 16. From 437a832f7a2bb8589a7096419d7c7f6144bc8591 Mon Sep 17 00:00:00 2001 From: tesseractjh Date: Wed, 3 Dec 2025 01:09:24 +0900 Subject: [PATCH 3/3] Allow arbitrary suffixes for use cache directives --- javascript/ql/lib/semmle/javascript/Stmt.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/Stmt.qll b/javascript/ql/lib/semmle/javascript/Stmt.qll index 453bc4076220..bbdf85df1b19 100644 --- a/javascript/ql/lib/semmle/javascript/Stmt.qll +++ b/javascript/ql/lib/semmle/javascript/Stmt.qll @@ -447,7 +447,7 @@ module Directive { * ``` */ class UseCacheDirective extends KnownDirective { - UseCacheDirective() { this.getDirectiveText().regexpMatch("use cache(: (remote|private))?") } + UseCacheDirective() { this.getDirectiveText().regexpMatch("use cache(:.*)?") } } }