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