Skip to content

Commit

Permalink
Add require-post-message-target-origin rule (#1326)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker authored Jun 4, 2021
1 parent cec7f11 commit 03c540b
Show file tree
Hide file tree
Showing 11 changed files with 336 additions and 6 deletions.
19 changes: 19 additions & 0 deletions docs/rules/require-post-message-target-origin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Enforce using the `targetOrigin` argument with `window.postMessage()`

When calling [`window.postMessage()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) without the `targetOrigin` argument, the message cannot be received by any window.

## Fail

```js
window.postMessage(message);
```

## Pass

```js
window.postMessage(message, 'https://example.com');
```

```js
window.postMessage(message, '*');
```
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ module.exports = {
'unicorn/prevent-abbreviations': 'error',
'unicorn/require-array-join-separator': 'error',
'unicorn/require-number-to-fixed-digits-argument': 'error',
'unicorn/require-post-message-target-origin': 'error',
'unicorn/string-content': 'off',
'unicorn/throw-new-error': 'error'
}
Expand Down
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ Configure it in `package.json`.
"unicorn/prevent-abbreviations": "error",
"unicorn/require-array-join-separator": "error",
"unicorn/require-number-to-fixed-digits-argument": "error",
"unicorn/require-post-message-target-origin": "error",
"unicorn/string-content": "off",
"unicorn/throw-new-error": "error"
}
Expand Down Expand Up @@ -217,6 +218,7 @@ Each rule has emojis denoting:
| [prevent-abbreviations](docs/rules/prevent-abbreviations.md) | Prevent abbreviations. || 🔧 | |
| [require-array-join-separator](docs/rules/require-array-join-separator.md) | Enforce using the separator argument with `Array#join()`. || 🔧 | |
| [require-number-to-fixed-digits-argument](docs/rules/require-number-to-fixed-digits-argument.md) | Enforce using the digits argument with `Number#toFixed()`. || 🔧 | |
| [require-post-message-target-origin](docs/rules/require-post-message-target-origin.md) | Enforce using the `targetOrigin` argument with `window.postMessage()`. || | 💡 |
| [string-content](docs/rules/string-content.md) | Enforce better string content. | | 🔧 | 💡 |
| [throw-new-error](docs/rules/throw-new-error.md) | Require `new` when throwing an error. || 🔧 | |

Expand Down
2 changes: 1 addition & 1 deletion rules/fix/append-argument.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function appendArgument(fixer, node, text, sourceCode) {

const [penultimateToken, lastToken] = sourceCode.getLastTokens(node, 2);
if (node.arguments.length > 0) {
text = isCommaToken(penultimateToken) ? `${text},` : `, ${text}`;
text = isCommaToken(penultimateToken) ? ` ${text},` : `, ${text}`;
}

return fixer.insertTextBefore(lastToken, text);
Expand Down
72 changes: 72 additions & 0 deletions rules/require-post-message-target-origin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'use strict';
const getDocumentationUrl = require('./utils/get-documentation-url');
const {methodCallSelector} = require('./selectors');
const {appendArgument} = require('./fix');

const ERROR = 'error';
const SUGGESTION_TARGET_LOCATION_ORIGIN = 'target-location-origin';
const SUGGESTION_SELF_LOCATION_ORIGIN = 'self-location-origin';
const SUGGESTION_STAR = 'star';
const messages = {
[ERROR]: 'Missing the `targetOrigin` argument.',
[SUGGESTION_TARGET_LOCATION_ORIGIN]: 'Use `{{target}}.location.origin`.',
[SUGGESTION_SELF_LOCATION_ORIGIN]: 'Use `self.location.origin`.',
[SUGGESTION_STAR]: 'Use `"*"`.'
};

/** @param {import('eslint').Rule.RuleContext} context */
function create(context) {
const sourceCode = context.getSourceCode();
return {
[methodCallSelector({name: 'postMessage', length: 1})](node) {
const [penultimateToken, lastToken] = sourceCode.getLastTokens(node, 2);
const suggestions = [];
const target = node.callee.object;
if (target.type === 'Identifier') {
const {name} = target;

suggestions.push({
messageId: SUGGESTION_TARGET_LOCATION_ORIGIN,
data: {target: name},
code: `${target.name}.location.origin`
});

if (name !== 'self' && name !== 'window' && name !== 'globalThis') {
suggestions.push({messageId: SUGGESTION_SELF_LOCATION_ORIGIN, code: 'self.location.origin'});
}
} else {
suggestions.push({messageId: SUGGESTION_SELF_LOCATION_ORIGIN, code: 'self.location.origin'});
}

suggestions.push({messageId: SUGGESTION_STAR, code: '\'*\''});

context.report({
loc: {
start: penultimateToken.loc.end,
end: lastToken.loc.end
},
messageId: ERROR,
suggest: suggestions.map(({messageId, data, code}) => ({
messageId,
data,
/** @param {import('eslint').Rule.RuleFixer} fixer */
fix: fixer => appendArgument(fixer, node, code, sourceCode)
}))
});
}
};
}

module.exports = {
create,
meta: {
type: 'problem',
docs: {
description: 'Enforce using the `targetOrigin` argument with `window.postMessage()`.',
url: getDocumentationUrl(__filename),
suggestion: true
},
schema: [],
messages
}
};
6 changes: 5 additions & 1 deletion scripts/create-rule.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ function updateIndex(id) {
},
{
message: 'No',
value: ''
value: false
}
]
},
Expand All @@ -133,6 +133,10 @@ function updateIndex(id) {
}
]);

if (data.fixableType === 'No') {
data.fixableType = false;
}

const {id} = data;

checkFiles(id);
Expand Down
31 changes: 31 additions & 0 deletions test/require-post-message-target-origin.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {getTester} from './utils/test.mjs';

const {test} = getTester(import.meta);

test.snapshot({
valid: [
'window.postMessage(message, targetOrigin)',
'postMessage(message)',
'window.postMessage',
'window.postMessage()',
'window.postMessage(message, targetOrigin, transfer)',
'window.postMessage(...message)',
'window[postMessage](message)',
'window["postMessage"](message)',
'window.notPostMessage(message)',
'window.postMessage?.(message)',
'window?.postMessage(message)'
],
invalid: [
'window.postMessage(message)',
'self.postMessage(message)',
'globalThis.postMessage(message)',
'foo.postMessage(message )',
'foo.postMessage( ((message)) )',
'foo.postMessage(message,)',
'foo.postMessage(message , )',
'foo.window.postMessage(message)',
'document.defaultView.postMessage(message)',
'getWindow().postMessage(message)'
]
});
8 changes: 4 additions & 4 deletions test/snapshots/require-array-join-separator.mjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Generated by [AVA](https://avajs.dev).
> Output
`␊
1 | [].join.call(foo,',',)␊
1 | [].join.call(foo, ',',)␊
`

> Error 1/1
Expand All @@ -58,7 +58,7 @@ Generated by [AVA](https://avajs.dev).
> Output
`␊
1 | [].join.call(foo , ',',);␊
1 | [].join.call(foo , ',',);␊
`

> Error 1/1
Expand Down Expand Up @@ -90,7 +90,7 @@ Generated by [AVA](https://avajs.dev).
> Output
`␊
1 | Array.prototype.join.call(foo, ',',)␊
1 | Array.prototype.join.call(foo, ',',)␊
`

> Error 1/1
Expand Down Expand Up @@ -155,7 +155,7 @@ Generated by [AVA](https://avajs.dev).
22 | /**/␊
23 | ,␊
24 | /**/␊
25 | ',',)/**/␊
25 | ',',)/**/␊
26 | )␊
`

Expand Down
Binary file modified test/snapshots/require-array-join-separator.mjs.snap
Binary file not shown.
Loading

0 comments on commit 03c540b

Please sign in to comment.