From bb72047b05f325db992cbc338f034874b1c9595b Mon Sep 17 00:00:00 2001 From: Kenzo-Wada Date: Sun, 28 Sep 2025 01:52:19 +0900 Subject: [PATCH 1/2] fix(linter/plugins): postmessage is not called on window (#12026) --- .../require_post_message_target_origin.rs | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/crates/oxc_linter/src/rules/unicorn/require_post_message_target_origin.rs b/crates/oxc_linter/src/rules/unicorn/require_post_message_target_origin.rs index e058db3a8e76f..27afb62f09a84 100644 --- a/crates/oxc_linter/src/rules/unicorn/require_post_message_target_origin.rs +++ b/crates/oxc_linter/src/rules/unicorn/require_post_message_target_origin.rs @@ -62,6 +62,9 @@ impl Rule for RequirePostMessageTargetOrigin { _ => return, }; if matches!(member_expr.static_property_name(), Some(name) if name == "postMessage") { + if is_message_port_expression(member_expr.object()) { + return; + } let span = call_expr.arguments[0].span(); ctx.diagnostic_with_suggestion( require_post_message_target_origin_diagnostic(Span::new(span.end, span.end)), @@ -79,6 +82,36 @@ impl Rule for RequirePostMessageTargetOrigin { } } +fn is_message_port_expression(expr: &Expression<'_>) -> bool { + let expr = expr.without_parentheses(); + + if let Expression::Identifier(ident) = expr + && matches!(ident.name.as_str(), "port" | "port1" | "port2" | "messagePort") + { + return true; + } + + let Some(member_expr) = expr.get_member_expr() else { + return false; + }; + + if member_expr.static_property_name().is_some_and(|name| matches!(name, "port1" | "port2")) { + return true; + } + + if member_expr.is_computed() + && member_expr.object().without_parentheses().get_member_expr().is_some_and( + |object_member| { + object_member.static_property_name().is_some_and(|name| name == "ports") + }, + ) + { + return true; + } + + is_message_port_expression(member_expr.object()) +} + #[test] fn test() { use crate::tester::Tester; @@ -101,6 +134,10 @@ fn test() { "window.c.postMessage?.(message)", "window.a.b?.postMessage(message)", "window?.a?.b?.postMessage(message)", + "event.ports[0].postMessage(message)", + "channel.port1.postMessage(message)", + "channel['port2'].postMessage(message)", + "event?.ports[0].postMessage(message)", ]; let fail = vec![ From e7c2611a8832258a8d7f245d3573ba30b5ac958e Mon Sep 17 00:00:00 2001 From: Kenzo Wada <79452224+Kenzo-Wada@users.noreply.github.com> Date: Sun, 28 Sep 2025 01:56:48 +0900 Subject: [PATCH 2/2] Update crates/oxc_linter/src/rules/unicorn/require_post_message_target_origin.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Kenzo Wada <79452224+Kenzo-Wada@users.noreply.github.com> --- .../require_post_message_target_origin.rs | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/crates/oxc_linter/src/rules/unicorn/require_post_message_target_origin.rs b/crates/oxc_linter/src/rules/unicorn/require_post_message_target_origin.rs index 27afb62f09a84..b35e46e1fd186 100644 --- a/crates/oxc_linter/src/rules/unicorn/require_post_message_target_origin.rs +++ b/crates/oxc_linter/src/rules/unicorn/require_post_message_target_origin.rs @@ -83,33 +83,34 @@ impl Rule for RequirePostMessageTargetOrigin { } fn is_message_port_expression(expr: &Expression<'_>) -> bool { - let expr = expr.without_parentheses(); + let mut current_expr = expr.without_parentheses(); + loop { + if let Expression::Identifier(ident) = current_expr + && matches!(ident.name.as_str(), "port" | "port1" | "port2" | "messagePort") + { + return true; + } - if let Expression::Identifier(ident) = expr - && matches!(ident.name.as_str(), "port" | "port1" | "port2" | "messagePort") - { - return true; - } + let Some(member_expr) = current_expr.get_member_expr() else { + return false; + }; - let Some(member_expr) = expr.get_member_expr() else { - return false; - }; + if member_expr.static_property_name().is_some_and(|name| matches!(name, "port1" | "port2")) { + return true; + } - if member_expr.static_property_name().is_some_and(|name| matches!(name, "port1" | "port2")) { - return true; - } + if member_expr.is_computed() + && member_expr.object().without_parentheses().get_member_expr().is_some_and( + |object_member| { + object_member.static_property_name().is_some_and(|name| name == "ports") + }, + ) + { + return true; + } - if member_expr.is_computed() - && member_expr.object().without_parentheses().get_member_expr().is_some_and( - |object_member| { - object_member.static_property_name().is_some_and(|name| name == "ports") - }, - ) - { - return true; + current_expr = member_expr.object().without_parentheses(); } - - is_message_port_expression(member_expr.object()) } #[test]