Skip to content

Commit

Permalink
no-document-cookie: Check window.document.cookie (#1833)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker committed Sep 20, 2022
1 parent 9ed08ab commit 0886544
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 39 deletions.
28 changes: 6 additions & 22 deletions rules/no-document-cookie.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,20 @@
'use strict';
const {getPropertyName} = require('eslint-utils');
const {GlobalReferenceTracker} = require('./utils/global-reference-tracker.js');

const MESSAGE_ID = 'no-document-cookie';
const messages = {
[MESSAGE_ID]: 'Do not use `document.cookie` directly.',
};

const selector = [
'AssignmentExpression',
'>',
'MemberExpression.left',
'[object.type="Identifier"]',
'[object.name="document"]',
].join('');

/** @param {import('eslint').Rule.RuleContext} context */
const create = context => ({
[selector](node) {
if (getPropertyName(node, context.getScope()) !== 'cookie') {
return;
}

return {
node,
messageId: MESSAGE_ID,
};
},
const tracker = new GlobalReferenceTracker({
object: 'document.cookie',
filter: ({node}) => node.parent.type === 'AssignmentExpression' && node.parent.left === node,
handle: ({node}) => ({node, messageId: MESSAGE_ID}),
});

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
create,
create: context => tracker.createListeners(context),
meta: {
type: 'problem',
docs: {
Expand Down
65 changes: 65 additions & 0 deletions rules/utils/global-reference-tracker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use strict';
const {ReferenceTracker} = require('eslint-utils');

const createTraceMap = object => {
let map = {[ReferenceTracker.READ]: true};

const path = object.split('.').reverse();
for (const name of path) {
map = {[name]: map};
}

return map;
};

class GlobalReferenceTracker {
#traceMap = {};
#filter;
#handle;

constructor({
object,
objects = [object],
filter,
handle,
}) {
for (const object of objects) {
Object.assign(this.#traceMap, createTraceMap(object));
}

this.#filter = filter;
this.#handle = handle;
}

* track(globalScope) {
const tracker = new ReferenceTracker(globalScope);

for (const reference of tracker.iterateGlobalReferences(this.#traceMap)) {
if (this.#filter && !this.#filter(reference)) {
continue;
}

const problems = this.#handle(reference);

if (!problems) {
continue;
}

if (problems[Symbol.iterator]) {
yield * problems;
} else {
yield problems;
}
}
}

createListeners(context) {
return {
'Program:exit': () => this.track(context.getScope()),
};
}
}

module.exports = {
GlobalReferenceTracker,
};
14 changes: 8 additions & 6 deletions test/no-document-cookie.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,21 @@ test.snapshot({
'Object.assign(document, {cookie: "foo=bar"})',
'document[CONSTANTS_COOKIE] = "foo=bar"',
'document[cookie] = "foo=bar"',
'var doc = document; doc.cookie = "foo=bar"',
'window.document.cookie = "foo=bar"',
outdent`
const CONSTANTS_COOKIE = "cookie";
document[CONSTANTS_COOKIE] = "foo=bar";
`,
],
invalid: [
'document.cookie = "foo=bar"',
'document.cookie += ";foo=bar"',
'document.cookie = document.cookie + ";foo=bar"',
'document.cookie &&= true',
outdent`
const CONSTANTS_COOKIE = "cookie";
document[CONSTANTS_COOKIE] = "foo=bar";
`,
'document["coo" + "kie"] = "foo=bar"',
'foo = document.cookie = "foo=bar"',
'var doc = document; doc.cookie = "foo=bar"',
'let doc = document; doc.cookie = "foo=bar"',
'const doc = globalThis.document; doc.cookie = "foo=bar"',
'window.document.cookie = "foo=bar"',
],
});
50 changes: 39 additions & 11 deletions test/snapshots/no-document-cookie.mjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,33 +45,61 @@ Generated by [AVA](https://avajs.dev).
`

## Invalid #5
1 | const CONSTANTS_COOKIE = "cookie";
2 | document[CONSTANTS_COOKIE] = "foo=bar";
1 | document["coo" + "kie"] = "foo=bar"

> Error 1/1
`␊
1 | const CONSTANTS_COOKIE = "cookie";␊
> 2 | document[CONSTANTS_COOKIE] = "foo=bar";␊
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use \`document.cookie\` directly.␊
> 1 | document["coo" + "kie"] = "foo=bar"␊
| ^^^^^^^^^^^^^^^^^^^^^^^ Do not use \`document.cookie\` directly.␊
`

## Invalid #6
1 | document["coo" + "kie"] = "foo=bar"
1 | foo = document.cookie = "foo=bar"

> Error 1/1
`␊
> 1 | document["coo" + "kie"] = "foo=bar"␊
| ^^^^^^^^^^^^^^^^^^^^^^^ Do not use \`document.cookie\` directly.␊
> 1 | foo = document.cookie = "foo=bar"␊
| ^^^^^^^^^^^^^^^ Do not use \`document.cookie\` directly.␊
`

## Invalid #7
1 | foo = document.cookie = "foo=bar"
1 | var doc = document; doc.cookie = "foo=bar"

> Error 1/1
`␊
> 1 | foo = document.cookie = "foo=bar"␊
| ^^^^^^^^^^^^^^^ Do not use \`document.cookie\` directly.␊
> 1 | var doc = document; doc.cookie = "foo=bar"␊
| ^^^^^^^^^^ Do not use \`document.cookie\` directly.␊
`

## Invalid #8
1 | let doc = document; doc.cookie = "foo=bar"

> Error 1/1
`␊
> 1 | let doc = document; doc.cookie = "foo=bar"␊
| ^^^^^^^^^^ Do not use \`document.cookie\` directly.␊
`

## Invalid #9
1 | const doc = globalThis.document; doc.cookie = "foo=bar"

> Error 1/1
`␊
> 1 | const doc = globalThis.document; doc.cookie = "foo=bar"␊
| ^^^^^^^^^^ Do not use \`document.cookie\` directly.␊
`

## Invalid #10
1 | window.document.cookie = "foo=bar"

> Error 1/1
`␊
> 1 | window.document.cookie = "foo=bar"␊
| ^^^^^^^^^^^^^^^^^^^^^^ Do not use \`document.cookie\` directly.␊
`
Binary file modified test/snapshots/no-document-cookie.mjs.snap
Binary file not shown.

0 comments on commit 0886544

Please sign in to comment.