| ... | @@ -24,6 +24,8 @@ type WhenToken = | ... | @@ -24,6 +24,8 @@ type WhenToken = |
| 24 | | { type: "lparen" } | 24 | | { type: "lparen" } |
| 25 | | { type: "rparen" }; | 25 | | { type: "rparen" }; |
| 26 | | 26 | |
| | 27 | const MAX_WHEN_EXPRESSION_DEPTH = 256; |
| | 28 | |
| 27 | export const DEFAULT_KEYBINDINGS: ReadonlyArray<KeybindingRule> = [ | 29 | export const DEFAULT_KEYBINDINGS: ReadonlyArray<KeybindingRule> = [ |
| 28 | { key: "mod+j", command: "terminal.toggle" }, | 30 | { key: "mod+j", command: "terminal.toggle" }, |
| 29 | { key: "mod+d", command: "terminal.split", when: "terminalFocus" }, | 31 | { key: "mod+d", command: "terminal.split", when: "terminalFocus" }, |
| ... | @@ -159,7 +161,10 @@ export function parseKeybindingWhenExpression(expression: string): KeybindingWhe | ... | @@ -159,7 +161,10 @@ export function parseKeybindingWhenExpression(expression: string): KeybindingWhe |
| 159 | if (!tokens || tokens.length === 0) return null; | 161 | if (!tokens || tokens.length === 0) return null; |
| 160 | let index = 0; | 162 | let index = 0; |
| 161 | | 163 | |
| 162 | const parsePrimary = (): KeybindingWhenNode | null => { | 164 | const parsePrimary = (depth: number): KeybindingWhenNode | null => { |
| | 165 | if (depth > MAX_WHEN_EXPRESSION_DEPTH) { |
| | 166 | return null; |
| | 167 | } |
| 163 | const token = tokens[index]; | 168 | const token = tokens[index]; |
| 164 | if (!token) return null; | 169 | if (!token) return null; |
| 165 | | 170 | |
| ... | @@ -170,7 +175,7 @@ export function parseKeybindingWhenExpression(expression: string): KeybindingWhe | ... | @@ -170,7 +175,7 @@ export function parseKeybindingWhenExpression(expression: string): KeybindingWhe |
| 170 | | 175 | |
| 171 | if (token.type === "lparen") { | 176 | if (token.type === "lparen") { |
| 172 | index += 1; | 177 | index += 1; |
| 173 | const expressionNode = parseOr(); | 178 | const expressionNode = parseOr(depth + 1); |
| 174 | const closeToken = tokens[index]; | 179 | const closeToken = tokens[index]; |
| 175 | if (!expressionNode || !closeToken || closeToken.type !== "rparen") { | 180 | if (!expressionNode || !closeToken || closeToken.type !== "rparen") { |
| 176 | return null; | 181 | return null; |
| ... | @@ -182,24 +187,34 @@ export function parseKeybindingWhenExpression(expression: string): KeybindingWhe | ... | @@ -182,24 +187,34 @@ export function parseKeybindingWhenExpression(expression: string): KeybindingWhe |
| 182 | return null; | 187 | return null; |
| 183 | }; | 188 | }; |
| 184 | | 189 | |
| 185 | const parseUnary = (): KeybindingWhenNode | null => { | 190 | const parseUnary = (depth: number): KeybindingWhenNode | null => { |
| 186 | const token = tokens[index]; | 191 | let notCount = 0; |
| 187 | if (token?.type === "not") { | 192 | while (tokens[index]?.type === "not") { |
| 188 | index += 1; | 193 | index += 1; |
| 189 | const node = parseUnary(); | 194 | notCount += 1; |
| 190 | if (!node) return null; | 195 | if (notCount > MAX_WHEN_EXPRESSION_DEPTH) { |
| 191 | return { type: "not", node }; | 196 | return null; |
| | 197 | } |
| 192 | } | 198 | } |
| 193 | return parsePrimary(); | 199 | |
| | 200 | let node = parsePrimary(depth); |
| | 201 | if (!node) return null; |
| | 202 | |
| | 203 | while (notCount > 0) { |
| | 204 | node = { type: "not", node }; |
| | 205 | notCount -= 1; |
| | 206 | } |
| | 207 | |
| | 208 | return node; |
| 194 | }; | 209 | }; |
| 195 | | 210 | |
| 196 | const parseAnd = (): KeybindingWhenNode | null => { | 211 | const parseAnd = (depth: number): KeybindingWhenNode | null => { |
| 197 | let left = parseUnary(); | 212 | let left = parseUnary(depth); |
| 198 | if (!left) return null; | 213 | if (!left) return null; |
| 199 | | 214 | |
| 200 | while (tokens[index]?.type === "and") { | 215 | while (tokens[index]?.type === "and") { |
| 201 | index += 1; | 216 | index += 1; |
| 202 | const right = parseUnary(); | 217 | const right = parseUnary(depth); |
| 203 | if (!right) return null; | 218 | if (!right) return null; |
| 204 | left = { type: "and", left, right }; | 219 | left = { type: "and", left, right }; |
| 205 | } | 220 | } |
| ... | @@ -207,13 +222,13 @@ export function parseKeybindingWhenExpression(expression: string): KeybindingWhe | ... | @@ -207,13 +222,13 @@ export function parseKeybindingWhenExpression(expression: string): KeybindingWhe |
| 207 | return left; | 222 | return left; |
| 208 | }; | 223 | }; |
| 209 | | 224 | |
| 210 | const parseOr = (): KeybindingWhenNode | null => { | 225 | const parseOr = (depth: number): KeybindingWhenNode | null => { |
| 211 | let left = parseAnd(); | 226 | let left = parseAnd(depth); |
| 212 | if (!left) return null; | 227 | if (!left) return null; |
| 213 | | 228 | |
| 214 | while (tokens[index]?.type === "or") { | 229 | while (tokens[index]?.type === "or") { |
| 215 | index += 1; | 230 | index += 1; |
| 216 | const right = parseAnd(); | 231 | const right = parseAnd(depth); |
| 217 | if (!right) return null; | 232 | if (!right) return null; |
| 218 | left = { type: "or", left, right }; | 233 | left = { type: "or", left, right }; |
| 219 | } | 234 | } |
| ... | @@ -221,7 +236,7 @@ export function parseKeybindingWhenExpression(expression: string): KeybindingWhe | ... | @@ -221,7 +236,7 @@ export function parseKeybindingWhenExpression(expression: string): KeybindingWhe |
| 221 | return left; | 236 | return left; |
| 222 | }; | 237 | }; |
| 223 | | 238 | |
| 224 | const ast = parseOr(); | 239 | const ast = parseOr(0); |
| 225 | if (!ast || index !== tokens.length) return null; | 240 | if (!ast || index !== tokens.length) return null; |
| 226 | return ast; | 241 | return ast; |
| 227 | } | 242 | } |