Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* Added `PreCallGraphStep` flow model for React's `useRef` hook.
* Added a `DomValueSource` that uses the `current` property off the object returned by React's `useRef` hook.
30 changes: 30 additions & 0 deletions javascript/ql/lib/semmle/javascript/frameworks/React.qll
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,25 @@ private class UseStateStep extends PreCallGraphStep {
}
}

/**
* Step through a `useRef` call.
*
* It returns an object with a single property (`current`) initialized to the initial value.
*
* For example:
* ```js
* const inputRef1 = useRef(initialValue);
* ```
*/
private class UseRefStep extends PreCallGraphStep {
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
exists(DataFlow::CallNode call | call = react().getAMemberCall("useRef") |
pred = call.getArgument(0) and // initial state
succ = call.getAPropertyRead("current")
)
}
}

/**
* A step through a React context object.
*
Expand Down Expand Up @@ -785,6 +804,17 @@ private class ReactRouterLocationSource extends DOM::LocationSource::Range {
}
}

private class UseRefDomValueSource extends DOM::DomValueSource::Range {
UseRefDomValueSource() {
this =
any(JsxAttribute attrib | attrib.getName() = "ref")
.getValue()
.flow()
.getALocalSource()
.getAPropertyRead("current")
}
}

/**
* Gets a reference to a function which, if called with a React component, returns wrapped
* version of that component, which we model as a direct reference to the underlying component.
Expand Down