diff --git a/src/browser/tests/event/keyboard.html b/src/browser/tests/event/keyboard.html
index 35ed4426..6f81a046 100644
--- a/src/browser/tests/event/keyboard.html
+++ b/src/browser/tests/event/keyboard.html
@@ -132,85 +132,33 @@
}
-
+ // Per Chrome behavior, both legacy `keyCode` and `charCode` return 0 for
+ // events constructed via `new KeyboardEvent(...)` because such events
+ // have `isTrusted === false`. The legacy mapping (a -> 65, Enter -> 13,
+ // etc.) is only exposed for events dispatched by the user agent itself.
+ // The full mapping table is exercised via Zig unit tests in
+ // `webapi/event/KeyboardEvent.zig`.
-
-
-
-
-
-
-
-
diff --git a/src/browser/webapi/event/KeyboardEvent.zig b/src/browser/webapi/event/KeyboardEvent.zig
index 6b837f6e..387a5d23 100644
--- a/src/browser/webapi/event/KeyboardEvent.zig
+++ b/src/browser/webapi/event/KeyboardEvent.zig
@@ -248,6 +248,18 @@ pub const Key = union(enum) {
else => 0,
};
}
+
+ /// Legacy `KeyboardEvent.charCode` value per UI Events spec § Annex C
+ /// (https://www.w3.org/TR/uievents/#legacy-key-attributes). Returns the
+ /// Unicode code point of the character produced by the key. Only
+ /// meaningful inside a `keypress` event — callers must gate accordingly.
+ pub fn charCode(self: Key) u32 {
+ return switch (self) {
+ .Enter => 13,
+ .standard => |s| if (s.len > 0) s[0] else 0,
+ else => 0,
+ };
+ }
};
pub const Location = enum(i32) {
@@ -362,17 +374,22 @@ pub fn getShiftKey(self: *const KeyboardEvent) bool {
// charCode is the Unicode code point of the character produced by the key,
// and is only meaningful on `keypress` events. For `keydown` and `keyup` it
// is 0. (Deprecated, but read by legacy event handlers.)
+//
+// Chrome returns 0 for synthetic events (those created via
+// `new KeyboardEvent(...)` rather than dispatched by the user agent), so we
+// gate on `_is_trusted` to match.
pub fn getCharCode(self: *const KeyboardEvent) u32 {
const event = self._proto._proto;
- if (!std.mem.eql(u8, event._type_string.str(), "keypress")) return 0;
- return switch (self._key) {
- .standard => |s| if (s.len > 0) s[0] else 0,
- else => 0,
- };
+ if (event._is_trusted == false) return 0;
+ if (event._type_string.eql(comptime .wrap("keypress")) == false) return 0;
+ return self._key.charCode();
}
// https://www.w3.org/TR/uievents/#dom-keyboardevent-keycode
+//
+// As with `charCode`, Chrome returns 0 for synthetic events.
pub fn getKeyCode(self: *const KeyboardEvent) u32 {
+ if (self._proto._proto._is_trusted == false) return 0;
return self._key.keyCode();
}
@@ -462,3 +479,77 @@ const testing = @import("../../../testing.zig");
test "WebApi: KeyboardEvent" {
try testing.htmlRunner("event/keyboard.html", .{});
}
+
+test "KeyboardEvent: Key.keyCode mapping" {
+ // Letters: uppercase ASCII regardless of case.
+ try testing.expectEqual(@as(u32, 65), Key.keyCode(.{ .standard = "a" }));
+ try testing.expectEqual(@as(u32, 65), Key.keyCode(.{ .standard = "A" }));
+ try testing.expectEqual(@as(u32, 84), Key.keyCode(.{ .standard = "T" }));
+ try testing.expectEqual(@as(u32, 90), Key.keyCode(.{ .standard = "z" }));
+
+ // Digits.
+ try testing.expectEqual(@as(u32, 48), Key.keyCode(.{ .standard = "0" }));
+ try testing.expectEqual(@as(u32, 53), Key.keyCode(.{ .standard = "5" }));
+ try testing.expectEqual(@as(u32, 57), Key.keyCode(.{ .standard = "9" }));
+
+ // Space.
+ try testing.expectEqual(@as(u32, 32), Key.keyCode(.{ .standard = " " }));
+
+ // Modifier keys.
+ try testing.expectEqual(@as(u32, 16), Key.keyCode(.Shift));
+ try testing.expectEqual(@as(u32, 17), Key.keyCode(.Control));
+ try testing.expectEqual(@as(u32, 18), Key.keyCode(.Alt));
+ try testing.expectEqual(@as(u32, 91), Key.keyCode(.Meta));
+ try testing.expectEqual(@as(u32, 20), Key.keyCode(.CapsLock));
+
+ // Whitespace keys.
+ try testing.expectEqual(@as(u32, 13), Key.keyCode(.Enter));
+ try testing.expectEqual(@as(u32, 9), Key.keyCode(.Tab));
+
+ // Navigation keys.
+ try testing.expectEqual(@as(u32, 37), Key.keyCode(.ArrowLeft));
+ try testing.expectEqual(@as(u32, 38), Key.keyCode(.ArrowUp));
+ try testing.expectEqual(@as(u32, 39), Key.keyCode(.ArrowRight));
+ try testing.expectEqual(@as(u32, 40), Key.keyCode(.ArrowDown));
+ try testing.expectEqual(@as(u32, 33), Key.keyCode(.PageUp));
+ try testing.expectEqual(@as(u32, 34), Key.keyCode(.PageDown));
+ try testing.expectEqual(@as(u32, 35), Key.keyCode(.End));
+ try testing.expectEqual(@as(u32, 36), Key.keyCode(.Home));
+
+ // Editing keys.
+ try testing.expectEqual(@as(u32, 8), Key.keyCode(.Backspace));
+ try testing.expectEqual(@as(u32, 46), Key.keyCode(.Delete));
+ try testing.expectEqual(@as(u32, 45), Key.keyCode(.Insert));
+
+ // UI keys.
+ try testing.expectEqual(@as(u32, 27), Key.keyCode(.Escape));
+ try testing.expectEqual(@as(u32, 19), Key.keyCode(.Pause));
+ try testing.expectEqual(@as(u32, 93), Key.keyCode(.ContextMenu));
+
+ // Function keys.
+ try testing.expectEqual(@as(u32, 112), Key.keyCode(.F1));
+ try testing.expectEqual(@as(u32, 123), Key.keyCode(.F12));
+
+ // Keys without a defined fixed virtual key code.
+ try testing.expectEqual(@as(u32, 0), Key.keyCode(.Dead));
+ try testing.expectEqual(@as(u32, 0), Key.keyCode(.Unidentified));
+ try testing.expectEqual(@as(u32, 0), Key.keyCode(.{ .standard = "" }));
+}
+
+test "KeyboardEvent: Key.charCode mapping" {
+ // Printable characters: Unicode code point of the first byte.
+ try testing.expectEqual(@as(u32, 97), Key.charCode(.{ .standard = "a" }));
+ try testing.expectEqual(@as(u32, 65), Key.charCode(.{ .standard = "A" }));
+ try testing.expectEqual(@as(u32, 48), Key.charCode(.{ .standard = "0" }));
+ try testing.expectEqual(@as(u32, 32), Key.charCode(.{ .standard = " " }));
+
+ // Enter is the one named key that produces a charCode (\r = 13).
+ try testing.expectEqual(@as(u32, 13), Key.charCode(.Enter));
+
+ // Other named keys and the empty standard key produce no character.
+ try testing.expectEqual(@as(u32, 0), Key.charCode(.Tab));
+ try testing.expectEqual(@as(u32, 0), Key.charCode(.Escape));
+ try testing.expectEqual(@as(u32, 0), Key.charCode(.ArrowLeft));
+ try testing.expectEqual(@as(u32, 0), Key.charCode(.Shift));
+ try testing.expectEqual(@as(u32, 0), Key.charCode(.{ .standard = "" }));
+}