implement Immutable merge

This commit is contained in:
Erik Krogh Kristensen
2021-02-04 11:48:30 +01:00
parent c0de6a3af2
commit b74df66463
3 changed files with 26 additions and 5 deletions

View File

@@ -36,12 +36,13 @@ private module Immutable {
* This predicate keeps track of which values in the program are Immutable collections.
*/
API::Node immutableCollection() {
// keep this predicate in sync with the constructors defined in `storeStep`.
result = immutableImport().getMember(["Map", "OrderedMap", "List", "fromJS"]).getReturn()
// keep this predicate in sync with the constructors defined in `storeStep`/`step`.
result =
immutableImport().getMember(["Map", "OrderedMap", "List", "fromJS", "merge"]).getReturn()
or
result = immutableImport().getMember("Record").getReturn().getReturn()
or
result = immutableCollection().getMember(["set", "map", "filter", "push"]).getReturn()
result = immutableCollection().getMember(["set", "map", "filter", "push", "merge"]).getReturn()
}
/**
@@ -125,6 +126,18 @@ private module Immutable {
pred = call.getReceiver() and
result = call
)
or
// Immutable.merge(x, y)
exists(DataFlow::CallNode call | call = immutableImport().getMember("merge").getACall() |
pred = call.getAnArgument() and
result = call
)
or
// collection.merge(other)
exists(DataFlow::CallNode call | call = immutableCollection().getMember("merge").getACall() |
pred = [call.getAnArgument(), call.getReceiver()] and
result = call
)
}
/**

View File

@@ -1,7 +1,7 @@
var obj = { a: source("a"), b: source("b1") };
sink(obj["a"]); // NOT OK
const { Map, fromJS, List, OrderedMap, Record } = require('immutable');
const { Map, fromJS, List, OrderedMap, Record, merge } = require('immutable');
const map1 = Map(obj);
@@ -39,4 +39,10 @@ sink(map4.get("f")); // NOT OK
const map5 = Record({a: source(), b: null, c: null})({b: source()});
sink(map5.get("a")); // NOT OK
sink(map5.get("b")); // NOT OK
sink(map5.get("c")); // OK
sink(map5.get("c")); // OK
const map6 = merge(Map({}), Record({a: source()})());
sink(map6.get("a")); // NOT OK
const map7 = map6.merge(Map({b: source()}));
sink(map7.get("b")); // NOT OK

View File

@@ -13,3 +13,5 @@
| immutable.js:36:38:36:45 | source() | immutable.js:37:6:37:18 | map4.get("f") |
| immutable.js:39:25:39:32 | source() | immutable.js:40:6:40:18 | map5.get("a") |
| immutable.js:39:58:39:65 | source() | immutable.js:41:6:41:18 | map5.get("b") |
| immutable.js:44:40:44:47 | source() | immutable.js:45:6:45:18 | map6.get("a") |
| immutable.js:47:33:47:40 | source() | immutable.js:48:6:48:18 | map7.get("b") |