Skip to content

matchesKey throws on a keydown event without a key #529

Description

@dongshunyao

Describe the bug

With a Layout mounted, a keydown event that carries no key makes the main layout's document listener throw TypeError: Cannot read properties of undefined (reading 'toLowerCase'). Browser autofill can send such events, and any script can dispatch one.

Your Example Website or App

The component in the steps below; no hosted copy.

Steps to Reproduce the Bug or Issue

  1. Render this component:
import { Layout, Model, TabNode } from "flexlayout-react";
import "flexlayout-react/style/light.css";

const model = Model.fromJson({
  global: {},
  borders: [],
  layout: {
    type: "row",
    children: [{ type: "tabset", children: [{ type: "tab", name: "One", component: "text" }] }],
  },
});

export default function App() {
  return (
    <div style={{ position: "absolute", inset: 0 }}>
      <Layout model={model} factory={(node: TabNode) => <div>{node.getName()}</div>} />
    </div>
  );
}
  1. In the browser console, run document.body.dispatchEvent(new Event("keydown", { bubbles: true })).

Expected behavior

The event is ignored.

Operating System

Windows 10 (10.0.19045)

Browser Type?

Chromium (the build that comes with Playwright 1.63; other browsers not tried)

Browser Version

153.0.8010.12

Screenshots or Videos

None. The page reports the uncaught error Cannot read properties of undefined (reading 'toLowerCase').

Additional context

flexlayout-react 0.11.0, React 18.3.1.

The main layout adds onOverlayBorderKeyDown to the document whether or not it has borders. It calls matchesKey (src/view/Utils.tsx:62), which reads event.key.toLowerCase() whenever the binding is set, and closeOverlayBorder defaults to "Escape". Returning false when event.key is not a string fixes it; I checked this with the same change made to a copy of dist/index.js:

 export function matchesKey(event: IKeyEventLike, spec: string | undefined): boolean {
-    if (!spec) {
+    if (!spec || typeof event.key !== "string") {
         return false;
     }

Apps without borders can work around it with keyMap={{ closeOverlayBorder: undefined }}.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions