Skip to content

Commit 9736a7f

Browse files
committed
refactor(linter): simplify unicorn/require-post-message-target-origin (#12110)
We are unable to correctly handle cases like `window.postMessage(message /** comments, */ )` due to the complexity of parsing trailing comments between arguments. To simplify the logic, we always append `, ...` after the first argument instead of trying to analyze whether a trailing comma or comment exists.
1 parent 2e3db46 commit 9736a7f

File tree

2 files changed

+46
-61
lines changed

2 files changed

+46
-61
lines changed

crates/oxc_linter/src/rules/unicorn/require_post_message_target_origin.rs

Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use oxc_diagnostics::OxcDiagnostic;
66
use oxc_macros::declare_oxc_lint;
77
use oxc_span::{GetSpan, Span};
88

9-
use crate::{AstNode, ast_util::is_method_call, context::LintContext, rule::Rule};
9+
use crate::{AstNode, context::LintContext, rule::Rule};
1010

1111
fn require_post_message_target_origin_diagnostic(span: Span) -> OxcDiagnostic {
1212
OxcDiagnostic::warn("Missing the `targetOrigin` argument.").with_label(span)
@@ -45,52 +45,37 @@ declare_oxc_lint!(
4545
);
4646

4747
impl Rule for RequirePostMessageTargetOrigin {
48-
#[expect(clippy::cast_possible_truncation)]
4948
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
5049
let AstKind::CallExpression(call_expr) = node.kind() else {
5150
return;
5251
};
53-
let arguments = &call_expr.arguments;
54-
if arguments.len() != 1 || call_expr.optional {
52+
// ignore "foo.postMessage?.(...message)" and "foo.postMessage(...message)"
53+
if call_expr.arguments.len() != 1
54+
|| call_expr.optional
55+
|| matches!(&call_expr.arguments[0], Argument::SpreadElement(_))
56+
{
5557
return;
5658
}
57-
let arg = &call_expr.arguments[0];
58-
// ignore "foo.postMessage(...message)"
59-
if matches!(arg, Argument::SpreadElement(_)) {
60-
return;
61-
}
62-
if !is_method_call(call_expr, None, Some(&["postMessage"]), Some(1), Some(1)) {
63-
return;
64-
}
65-
// ignore "foo['postMessage'](message)"
66-
let Some(member_expr) = call_expr.callee.as_member_expression() else {
67-
return;
59+
let member_expr = match call_expr.callee.get_member_expr() {
60+
// ignore "foo[postMessage](message)" and "foo?.postMessage(message)"
61+
Some(expr) if !(expr.is_computed() || expr.optional()) => expr,
62+
_ => return,
6863
};
69-
// ignore "foo[postMessage](message)" and "foo?.postMessage(message)"
70-
if member_expr.is_computed() || member_expr.optional() {
71-
return;
64+
if matches!(member_expr.static_property_name(), Some(name) if name == "postMessage") {
65+
let span = call_expr.arguments[0].span();
66+
ctx.diagnostic_with_suggestion(
67+
require_post_message_target_origin_diagnostic(Span::new(span.end, span.end)),
68+
|fixer| {
69+
let text = match member_expr.object() {
70+
Expression::Identifier(ident) => {
71+
format!(", {}.location.origin", ident.name.as_str())
72+
}
73+
_ => ", self.location.origin".to_string(),
74+
};
75+
fixer.insert_text_after_range(span, text)
76+
},
77+
);
7278
}
73-
74-
let comma_idx =
75-
Span::new(arg.span().end, call_expr.span.end).source_text(ctx.source_text()).find(',');
76-
let offset = comma_idx.unwrap_or(0) as u32;
77-
let target_span = Span::new(arg.span().end + offset, call_expr.span.end);
78-
ctx.diagnostic_with_suggestion(
79-
require_post_message_target_origin_diagnostic(target_span),
80-
|fixer| {
81-
let last_token = Span::new(call_expr.span.end - 1, call_expr.span.end);
82-
let text = match member_expr.object() {
83-
Expression::Identifier(ident) => {
84-
format!("{}.location.origin", ident.name.as_str())
85-
}
86-
_ => "self.location.origin".to_string(),
87-
};
88-
89-
let replacement =
90-
if comma_idx.is_some() { format!(" {text},") } else { format!(", {text}") };
91-
fixer.insert_text_before(&last_token, replacement)
92-
},
93-
);
9479
}
9580
}
9681

@@ -149,15 +134,15 @@ fn test() {
149134
"globalThis.postMessage(message, globalThis.location.origin)",
150135
None,
151136
),
152-
("foo.postMessage(message )", "foo.postMessage(message , foo.location.origin)", None),
137+
("foo.postMessage(message )", "foo.postMessage(message, foo.location.origin )", None),
153138
(
154139
"window.postMessage(message,)",
155140
"window.postMessage(message, window.location.origin,)",
156141
None,
157142
),
158143
(
159144
"window.postMessage(message, /** comments */ )",
160-
"window.postMessage(message, /** comments */ window.location.origin,)",
145+
"window.postMessage(message, window.location.origin, /** comments */ )",
161146
None,
162147
),
163148
(

crates/oxc_linter/src/snapshots/unicorn_require_post_message_target_origin.snap

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,111 +4,111 @@ source: crates/oxc_linter/src/tester.rs
44
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
55
╭─[require_post_message_target_origin.tsx:1:27]
66
1window.postMessage(message)
7-
·
7+
·
88
╰────
99
help: Insert `, window.location.origin`
1010

1111
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
1212
╭─[require_post_message_target_origin.tsx:1:25]
1313
1self.postMessage(message)
14-
·
14+
·
1515
╰────
1616
help: Insert `, self.location.origin`
1717

1818
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
1919
╭─[require_post_message_target_origin.tsx:1:31]
2020
1globalThis.postMessage(message)
21-
·
21+
·
2222
╰────
2323
help: Insert `, globalThis.location.origin`
2424

2525
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
2626
╭─[require_post_message_target_origin.tsx:1:24]
2727
1foo.postMessage(message )
28-
· ──
28+
·
2929
╰────
3030
help: Insert `, foo.location.origin`
3131

3232
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
3333
╭─[require_post_message_target_origin.tsx:1:29]
3434
1foo.postMessage( ((message)) )
35-
· ──
35+
·
3636
╰────
3737
help: Insert `, foo.location.origin`
3838

3939
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
4040
╭─[require_post_message_target_origin.tsx:1:24]
4141
1foo.postMessage(message,)
42-
· ──
42+
·
4343
╰────
44-
help: Insert ` foo.location.origin,`
44+
help: Insert `, foo.location.origin`
4545

4646
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
47-
╭─[require_post_message_target_origin.tsx:1:25]
47+
╭─[require_post_message_target_origin.tsx:1:24]
4848
1foo.postMessage(message , )
49-
· ───
49+
·
5050
╰────
51-
help: Insert ` foo.location.origin,`
51+
help: Insert `, foo.location.origin`
5252

5353
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
5454
╭─[require_post_message_target_origin.tsx:1:31]
5555
1foo.window.postMessage(message)
56-
·
56+
·
5757
╰────
5858
help: Insert `, self.location.origin`
5959

6060
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
6161
╭─[require_post_message_target_origin.tsx:1:41]
6262
1document.defaultView.postMessage(message)
63-
·
63+
·
6464
╰────
6565
help: Insert `, self.location.origin`
6666

6767
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
6868
╭─[require_post_message_target_origin.tsx:1:32]
6969
1getWindow().postMessage(message)
70-
·
70+
·
7171
╰────
7272
help: Insert `, self.location.origin`
7373

7474
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
7575
╭─[require_post_message_target_origin.tsx:1:27]
7676
1window.postMessage(message, /** comments */ )
77-
· ────────────────────────────────────
77+
·
7878
╰────
79-
help: Insert ` window.location.origin,`
79+
help: Insert `, window.location.origin`
8080

8181
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
8282
╭─[require_post_message_target_origin.tsx:1:29]
8383
1window.c.postMessage(message)
84-
·
84+
·
8585
╰────
8686
help: Insert `, self.location.origin`
8787

8888
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
8989
╭─[require_post_message_target_origin.tsx:1:30]
9090
1window?.c.postMessage(message)
91-
·
91+
·
9292
╰────
9393
help: Insert `, self.location.origin`
9494

9595
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
9696
╭─[require_post_message_target_origin.tsx:1:32]
9797
1window?.a.b.postMessage(message)
98-
·
98+
·
9999
╰────
100100
help: Insert `, self.location.origin`
101101

102102
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
103103
╭─[require_post_message_target_origin.tsx:1:32]
104104
1window.a?.b.postMessage(message)
105-
·
105+
·
106106
╰────
107107
help: Insert `, self.location.origin`
108108

109109
eslint-plugin-unicorn(require-post-message-target-origin): Missing the `targetOrigin` argument.
110110
╭─[require_post_message_target_origin.tsx:1:33]
111111
1window?.a?.b.postMessage(message)
112-
·
112+
·
113113
╰────
114114
help: Insert `, self.location.origin`

0 commit comments

Comments
 (0)