Skip to content

Commit

Permalink
more wip
Browse files Browse the repository at this point in the history
  • Loading branch information
bschlenk committed Sep 23, 2023
1 parent 008dfc6 commit f608c8f
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 28 deletions.
44 changes: 17 additions & 27 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint no-nested-ternary: off */
import type { Rule } from "eslint";
import type * as ESTree from "estree";
import browserslist from "browserslist";
Expand All @@ -15,40 +14,34 @@ import { TargetNameMappings } from "./constants";
- Each API is given to versioning.ts with compatibility info
*/

enum GuardType {
// Guard is true if the browser supports the API
POSITIVE,
// Guard is false if the browser supports the API
NEGATIVE,
}

export interface GuardedScope {
scope: ESTree.Node & Rule.NodeParentExtension;
scope: Rule.Node;
index: number;
}

/**
* Checks if the given node is used in a guard, and whether it's used to guard for or against the
* block statement. Should be called with either a bare Identifier, or a MemberExpression.
* Checks if the given node is used in an if statement, and if it is, returns the
* scope that the guard applies to and after which index it applies.
* Should be called with either a bare Identifier or a MemberExpression.
*/
export function determineGuardedScope(
node: (ESTree.Identifier | ESTree.MemberExpression) & Rule.NodeParentExtension
): GuardedScope | null {
const result = getIfStatementAndGuardType(node);
if (!result) return null;

const [ifStatement, guardType] = result;
const [ifStatement, positiveGuard] = result;

if (guardType === GuardType.POSITIVE) {
return { scope: ifStatement.consequent as GuardedScope["scope"], index: 0 };
if (positiveGuard) {
// It's okay to use the identifier inside of the if statement
return { scope: ifStatement.consequent as Rule.Node, index: 0 };
}

// guardType is NEGATIVE

if (
ifStatementHasEarlyReturn(ifStatement) &&
isBlockOrProgram(ifStatement.parent)
) {
// It's okay to use the identifier after the if statement
const scope = ifStatement.parent;
const index = scope.body.indexOf(ifStatement) + 1;
return { scope, index };
Expand All @@ -65,9 +58,9 @@ export function isBlockOrProgram(

function getIfStatementAndGuardType(
node: (ESTree.Identifier | ESTree.MemberExpression) & Rule.NodeParentExtension
): [ESTree.IfStatement & Rule.NodeParentExtension, GuardType] | null {
let guardType = GuardType.POSITIVE;
let expression: ESTree.Node & Rule.NodeParentExtension = node;
): [ESTree.IfStatement & Rule.NodeParentExtension, boolean] | null {
let positiveGuard = true;
let expression: Rule.Node = node;

if (
node.parent?.type === "UnaryExpression" &&
Expand All @@ -92,11 +85,11 @@ function getIfStatementAndGuardType(
) {
// typeof foo === "function"
// typeof foo !== "undefined"
guardType = GuardType.POSITIVE;
positiveGuard = true;
} else {
// typeof foo !== "function"
// typepf foo === "undefined"
guardType = GuardType.NEGATIVE;
positiveGuard = false;
}
}

Expand All @@ -109,20 +102,17 @@ function getIfStatementAndGuardType(
expression.parent.operator === "!"
) {
expression = expression.parent;
if (guardType === GuardType.POSITIVE) {
guardType = GuardType.NEGATIVE;
} else {
guardType = GuardType.POSITIVE;
}
positiveGuard = !positiveGuard;
}

// TODO: allow && checks, but || checks aren't really safe
// skip over && and || expressions
while (expression.parent?.type === "LogicalExpression") {
expression = expression.parent;
}

if (expression.parent?.type === "IfStatement") {
return [expression.parent, guardType];
return [expression.parent, positiveGuard];
}

return null;
Expand Down
2 changes: 1 addition & 1 deletion src/rules/compat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ const ruleModule: Rule.RuleModule = {

let object = "window";

let expression: ESTree.Node & Rule.NodeParentExtension = node;
let expression: Rule.Node = node;
if (expression.parent.type === "MemberExpression") {
expression = expression.parent;
if (expression.object.type === "MemberExpression") {
Expand Down

0 comments on commit f608c8f

Please sign in to comment.