Skip to content

Commit e559009

Browse files
authored
Merge pull request github#3109 from max-schaefer/js/performance-fixes
Approved by asgerf
2 parents 1346592 + 55e7b22 commit e559009

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

javascript/ql/src/semmle/javascript/Promises.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ module PromiseTypeTracking {
184184
* Gets the result from a single step through a promise, from `pred` with tracker `t2` to `result` with tracker `t`.
185185
* This can be loading a resolved value from a promise, storing a value in a promise, or copying a resolved value from one promise to another.
186186
*/
187+
pragma[inline]
187188
DataFlow::SourceNode promiseStep(
188189
DataFlow::SourceNode pred, DataFlow::TypeTracker t, DataFlow::TypeTracker t2
189190
) {

javascript/ql/src/semmle/javascript/dataflow/Configuration.qll

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -958,18 +958,31 @@ private predicate reachableFromStoreBase(
958958
s2.getEndLabel())
959959
)
960960
or
961-
exists(DataFlow::Node mid, PathSummary oldSummary, PathSummary newSummary |
962-
reachableFromStoreBase(prop, rhs, mid, cfg, oldSummary) and
963-
(
964-
flowStep(mid, cfg, nd, newSummary)
965-
or
966-
isAdditionalLoadStoreStep(mid, nd, prop, cfg) and
967-
newSummary = PathSummary::level()
968-
) and
961+
exists(PathSummary oldSummary, PathSummary newSummary |
962+
reachableFromStoreBaseStep(prop, rhs, nd, cfg, oldSummary, newSummary) and
969963
summary = oldSummary.appendValuePreserving(newSummary)
970964
)
971965
}
972966

967+
/**
968+
* Holds if `rhs` is the right-hand side of a write to property `prop`, and `nd` is reachable
969+
* from the base of that write under configuration `cfg` (possibly through callees) along a
970+
* path whose last step is summarized by `newSummary`, and the previous steps are summarized
971+
* by `oldSummary`.
972+
*/
973+
pragma[noinline]
974+
private predicate reachableFromStoreBaseStep(
975+
string prop, DataFlow::Node rhs, DataFlow::Node nd, DataFlow::Configuration cfg,
976+
PathSummary oldSummary, PathSummary newSummary
977+
) {
978+
exists(DataFlow::Node mid | reachableFromStoreBase(prop, rhs, mid, cfg, oldSummary) |
979+
flowStep(mid, cfg, nd, newSummary)
980+
or
981+
isAdditionalLoadStoreStep(mid, nd, prop, cfg) and
982+
newSummary = PathSummary::level()
983+
)
984+
}
985+
973986
/**
974987
* Holds if the value of `pred` is written to a property of some base object, and that base
975988
* object may flow into the base of property read `succ` under configuration `cfg` along
@@ -981,13 +994,29 @@ pragma[noinline]
981994
private predicate flowThroughProperty(
982995
DataFlow::Node pred, DataFlow::Node succ, DataFlow::Configuration cfg, PathSummary summary
983996
) {
984-
exists(string prop, DataFlow::Node base, PathSummary oldSummary, PathSummary newSummary |
985-
reachableFromStoreBase(prop, pred, base, cfg, oldSummary) and
986-
loadStep(base, succ, prop, cfg, newSummary) and
997+
exists(PathSummary oldSummary, PathSummary newSummary |
998+
storeToLoad(pred, succ, cfg, oldSummary, newSummary) and
987999
summary = oldSummary.append(newSummary)
9881000
)
9891001
}
9901002

1003+
/**
1004+
* Holds if the value of `pred` is written to a property of some base object, and that base
1005+
* object may flow into the base of property read `succ` under configuration `cfg` along
1006+
* a path whose last step is summarized by `newSummary`, and the previous steps are summarized
1007+
* by `oldSummary`.
1008+
*/
1009+
pragma[noinline]
1010+
private predicate storeToLoad(
1011+
DataFlow::Node pred, DataFlow::Node succ, DataFlow::Configuration cfg, PathSummary oldSummary,
1012+
PathSummary newSummary
1013+
) {
1014+
exists(string prop, DataFlow::Node base |
1015+
reachableFromStoreBase(prop, pred, base, cfg, oldSummary) and
1016+
loadStep(base, succ, prop, cfg, newSummary)
1017+
)
1018+
}
1019+
9911020
/**
9921021
* Holds if `arg` and `cb` are passed as arguments to a function which in turn
9931022
* invokes `cb`, passing `arg` as its `i`th argument.

javascript/ql/src/semmle/javascript/dataflow/Nodes.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,12 @@ class InvokeNode extends DataFlow::SourceNode {
157157
* `name` is set to `result`.
158158
*/
159159
DataFlow::ValueNode getOptionArgument(int i, string name) {
160-
exists(ObjectLiteralNode obj |
161-
obj.flowsTo(getArgument(i)) and
162-
obj.hasPropertyWrite(name, result)
163-
)
160+
getOptionsArgument(i).hasPropertyWrite(name, result)
164161
}
165162

163+
pragma[noinline]
164+
private ObjectLiteralNode getOptionsArgument(int i) { result.flowsTo(getArgument(i)) }
165+
166166
/** Gets an abstract value representing possible callees of this call site. */
167167
final AbstractValue getACalleeValue() { result = getCalleeNode().analyze().getAValue() }
168168

0 commit comments

Comments
 (0)