From f49ebebd7d1be30d2cfc597937e2c11d9c0db35e Mon Sep 17 00:00:00 2001 From: jketema <93738568+jketema@users.noreply.github.com> Date: Wed, 30 Sep 2026 13:32:33 +0000 Subject: [PATCH] JS: Recognize Workflow SDK 'use workflow' and 'use step' directives Fixes #22701 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../2026-09-30-workflow-sdk-directives.md | 4 +++ javascript/ql/lib/semmle/javascript/Stmt.qll | 26 +++++++++++++++++++ .../Directives/KnownDirective.expected | 4 ++- .../ql/test/library-tests/Directives/tst.js | 2 ++ .../UnknownDirective.expected | 8 +++--- .../UnknownDirective/UnknownDirective.js | 2 ++ 6 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 javascript/ql/lib/change-notes/2026-09-30-workflow-sdk-directives.md diff --git a/javascript/ql/lib/change-notes/2026-09-30-workflow-sdk-directives.md b/javascript/ql/lib/change-notes/2026-09-30-workflow-sdk-directives.md new file mode 100644 index 000000000000..ccbe08aba242 --- /dev/null +++ b/javascript/ql/lib/change-notes/2026-09-30-workflow-sdk-directives.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The Workflow SDK directives `"use workflow"` and `"use step"` are now recognized as known directives, so the `js/unknown-directive` query no longer flags them. diff --git a/javascript/ql/lib/semmle/javascript/Stmt.qll b/javascript/ql/lib/semmle/javascript/Stmt.qll index cedc3da2e8cb..e709c7217eb2 100644 --- a/javascript/ql/lib/semmle/javascript/Stmt.qll +++ b/javascript/ql/lib/semmle/javascript/Stmt.qll @@ -490,6 +490,32 @@ module Directive { class WorkletDirective extends KnownDirective { WorkletDirective() { this.getDirectiveText() = "worklet" } } + + /** + * A Workflow SDK `use workflow` directive. + * + * Example: + * + * ``` + * "use workflow"; + * ``` + */ + class UseWorkflowDirective extends KnownDirective { + UseWorkflowDirective() { this.getDirectiveText() = "use workflow" } + } + + /** + * A Workflow SDK `use step` directive. + * + * Example: + * + * ``` + * "use step"; + * ``` + */ + class UseStepDirective extends KnownDirective { + UseStepDirective() { this.getDirectiveText() = "use step" } + } } /** diff --git a/javascript/ql/test/library-tests/Directives/KnownDirective.expected b/javascript/ql/test/library-tests/Directives/KnownDirective.expected index 89efb1e24dcd..50fb4593dcf4 100644 --- a/javascript/ql/test/library-tests/Directives/KnownDirective.expected +++ b/javascript/ql/test/library-tests/Directives/KnownDirective.expected @@ -19,4 +19,6 @@ | tst.js:27:3:27:14 | 'use cache'; | use cache | | tst.js:28:3:28:22 | 'use cache: remote'; | use cache: remote | | tst.js:29:3:29:23 | 'use ca ... ivate'; | use cache: private | -| tst.js:36:5:36:17 | 'use strict'; | use strict | +| tst.js:30:3:30:17 | 'use workflow'; | use workflow | +| tst.js:31:3:31:13 | 'use step'; | use step | +| tst.js:38:5:38: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 30a0772a610e..676972b99825 100644 --- a/javascript/ql/test/library-tests/Directives/tst.js +++ b/javascript/ql/test/library-tests/Directives/tst.js @@ -27,6 +27,8 @@ function f() { 'use cache'; 'use cache: remote'; 'use cache: private'; + 'use workflow'; + 'use step'; ; '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 4d089fdba5be..d19dd5d69d88 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: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)'. | +| UnknownDirective.js:45:5:45:17 | "[0, 0, 0];"; | Unknown directive: '[0, 0, 0];'. | +| UnknownDirective.js:46:5:46:65 | "[0, 0, ... , 0];"; | Unknown directive: '[0, 0, 0, 0, 0, 0, 0 ... (truncated)'. | +| UnknownDirective.js:52:5:52:15 | ":nomunge"; | Unknown directive: ':nomunge'. | +| UnknownDirective.js:53:5:53: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 78c0d79f2c1a..5e4d18a381e0 100644 --- a/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.js +++ b/javascript/ql/test/query-tests/Expressions/UnknownDirective/UnknownDirective.js @@ -37,6 +37,8 @@ function good() { "use cache"; "use cache: remote"; "use cache: private"; + "use workflow"; + "use step"; } function data() {