Merge pull request #1032 from xiemaisi/master-for-merge

Merge master into rc/1.20
This commit is contained in:
Max Schaefer
2019-03-04 21:23:51 +00:00
committed by GitHub
452 changed files with 32902 additions and 30435 deletions

View File

@@ -0,0 +1,3 @@
| tst2.js:3:14:3:14 | x | tst2.js:7:5:7:10 | this.x |
| tst2.js:3:14:3:14 | x | tst2.js:8:25:8:30 | this.x |
| tst2.js:3:14:3:14 | x | tst2.js:12:12:12:17 | this.x |

View File

@@ -0,0 +1,5 @@
import javascript
from DataFlow::Node pred, DataFlow::Node succ
where DataFlow::localFieldStep(pred, succ)
select pred, succ

View File

@@ -1,4 +1,6 @@
| namespace.js:5:32:5:44 | function() {} | Baz.method | method |
| tst2.js:6:9:9:3 | () {\\n ... .x;\\n } | C.method | method |
| tst2.js:11:13:13:3 | () {\\n ... .x;\\n } | C.getter | getter |
| tst.js:4:17:4:21 | () {} | A.instanceMethod | method |
| tst.js:7:6:7:10 | () {} | A.bar | method |
| tst.js:9:10:9:14 | () {} | A.baz | getter |

View File

@@ -1,4 +1,5 @@
| namespace.js:5:32:5:44 | function() {} | Baz.method |
| tst2.js:6:9:9:3 | () {\\n ... .x;\\n } | C.method |
| tst.js:4:17:4:21 | () {} | A.instanceMethod |
| tst.js:7:6:7:10 | () {} | A.bar |
| tst.js:17:19:17:31 | function() {} | B.foo |

View File

@@ -0,0 +1,18 @@
| namespace.js:3:15:3:31 | function Baz() {} | namespace.js:3:15:3:14 | this |
| namespace.js:3:15:3:31 | function Baz() {} | namespace.js:5:32:5:31 | this |
| tst2.js:1:1:14:1 | class C ... ;\\n }\\n} | tst2.js:2:14:2:13 | this |
| tst2.js:1:1:14:1 | class C ... ;\\n }\\n} | tst2.js:6:9:6:8 | this |
| tst2.js:1:1:14:1 | class C ... ;\\n }\\n} | tst2.js:11:13:11:12 | this |
| tst.js:3:1:10:1 | class A ... () {}\\n} | tst.js:3:9:3:8 | this |
| tst.js:3:1:10:1 | class A ... () {}\\n} | tst.js:4:17:4:16 | this |
| tst.js:3:1:10:1 | class A ... () {}\\n} | tst.js:7:6:7:5 | this |
| tst.js:3:1:10:1 | class A ... () {}\\n} | tst.js:9:10:9:9 | this |
| tst.js:13:1:13:21 | class A ... ds A {} | tst.js:13:20:13:19 | this |
| tst.js:15:1:15:15 | function B() {} | tst.js:15:1:15:0 | this |
| tst.js:15:1:15:15 | function B() {} | tst.js:17:19:17:18 | this |
| tst.js:19:1:19:15 | function C() {} | tst.js:19:1:19:0 | this |
| tst.js:19:1:19:15 | function C() {} | tst.js:21:19:21:18 | this |
| tst.js:23:1:23:15 | function D() {} | tst.js:23:1:23:0 | this |
| tst.js:23:1:23:15 | function D() {} | tst.js:25:13:25:12 | this |
| tst.js:23:1:23:15 | function D() {} | tst.js:26:13:26:12 | this |
| tst.js:23:1:23:15 | function D() {} | tst.js:27:4:27:3 | this |

View File

@@ -0,0 +1,4 @@
import javascript
from DataFlow::ClassNode cls
select cls, cls.getAReceiverNode()

View File

@@ -0,0 +1,14 @@
class C {
constructor(x) {
this.x = x;
}
method() {
this.x;
let closure = () => this.x;
}
get getter() {
return this.x;
}
}

View File

@@ -0,0 +1,25 @@
| method-calls.js:2:11:7:2 | {\\n\\t\\tm1: ... }; }\\n\\t} |
| method-calls.js:11:23:11:24 | {} |
| method-calls.js:16:11:16:12 | {} |
| method-calls.js:25:11:25:17 | {m: f1} |
| method-calls.js:29:11:29:17 | {m: f2} |
| method-calls.js:34:12:34:18 | {m: f3} |
| method-calls.js:38:15:38:21 | {m: f4} |
| method-calls.js:46:16:46:28 | {m: () => 42} |
| method-calls.js:50:17:50:29 | {m: () => 42} |
| method-calls.js:54:16:54:28 | {m: () => 42} |
| method-calls.js:57:16:57:28 | {m: () => 42} |
| tst.js:3:18:3:19 | {} |
| tst.js:4:18:4:36 | { f: function(){} } |
| tst.js:5:18:5:34 | { [unknown]: 42 } |
| tst.js:38:18:38:26 | { p: 42 } |
| tst.js:42:18:42:33 | { p: 42, q: 42 } |
| tst.js:52:23:52:24 | {} |
| tst.js:56:20:56:35 | { p: 42, p: 42 } |
| tst.js:59:20:59:28 | { p: 42 } |
| tst.js:63:20:63:28 | { p: 42 } |
| tst.js:68:19:68:27 | { p: 42 } |
| tst.js:73:18:73:20 | { } |
| tst.js:76:18:76:26 | { p: 42 } |
| tst.js:77:18:77:28 | { p: true } |
| tst.js:82:20:82:21 | {} |

View File

@@ -0,0 +1,4 @@
import javascript
import semmle.javascript.dataflow.LocalObjects
select any(LocalObject n)

View File

@@ -0,0 +1,22 @@
| method-calls.js:2:11:7:2 | {\\n\\t\\tm1: ... }; }\\n\\t} | m1 |
| method-calls.js:2:11:7:2 | {\\n\\t\\tm1: ... }; }\\n\\t} | m2 |
| method-calls.js:2:11:7:2 | {\\n\\t\\tm1: ... }; }\\n\\t} | m3 |
| method-calls.js:2:11:7:2 | {\\n\\t\\tm1: ... }; }\\n\\t} | m4 |
| method-calls.js:25:11:25:17 | {m: f1} | m |
| method-calls.js:29:11:29:17 | {m: f2} | m |
| method-calls.js:34:12:34:18 | {m: f3} | m |
| method-calls.js:38:15:38:21 | {m: f4} | m |
| method-calls.js:46:16:46:28 | {m: () => 42} | m |
| method-calls.js:50:17:50:29 | {m: () => 42} | m |
| method-calls.js:54:16:54:28 | {m: () => 42} | m |
| method-calls.js:57:16:57:28 | {m: () => 42} | m |
| tst.js:4:18:4:36 | { f: function(){} } | f |
| tst.js:38:18:38:26 | { p: 42 } | p |
| tst.js:42:18:42:33 | { p: 42, q: 42 } | p |
| tst.js:42:18:42:33 | { p: 42, q: 42 } | q |
| tst.js:56:20:56:35 | { p: 42, p: 42 } | p |
| tst.js:59:20:59:28 | { p: 42 } | p |
| tst.js:63:20:63:28 | { p: 42 } | p |
| tst.js:68:19:68:27 | { p: 42 } | p |
| tst.js:76:18:76:26 | { p: 42 } | p |
| tst.js:77:18:77:28 | { p: true } | p |

View File

@@ -0,0 +1,6 @@
import javascript
import semmle.javascript.dataflow.LocalObjects
from LocalObject src, string name
where src.hasOwnProperty(name)
select src, name

View File

@@ -0,0 +1,12 @@
| method-calls.js:8:2:8:8 | o1.m1() | object |
| method-calls.js:9:2:9:8 | o1.m2() | object |
| method-calls.js:12:2:12:7 | o.m3() | boolean, class, date, function, null, number, object, regular expression,string or undefined |
| method-calls.js:21:2:21:7 | o2.m() | boolean, class, date, function, null, number, object, regular expression,string or undefined |
| method-calls.js:25:11:25:21 | {m: f1}.m() | object |
| method-calls.js:30:11:30:16 | o2.m() | object |
| method-calls.js:34:11:34:23 | ({m: f3}).m() | object |
| method-calls.js:41:11:41:16 | o4.m() | boolean, class, date, function, null, number, object, regular expression,string or undefined |
| method-calls.js:47:12:47:16 | o.m() | boolean, class, date, function, null, number, object, regular expression,string or undefined |
| method-calls.js:51:12:51:16 | o.m() | boolean, class, date, function, null, number, object, regular expression,string or undefined |
| method-calls.js:55:12:55:16 | o.m() | boolean, class, date, function, null, number, object, regular expression,string or undefined |
| method-calls.js:60:12:60:16 | o.m() | boolean, class, date, function, null, number, object, regular expression,string or undefined |

View File

@@ -0,0 +1,4 @@
import javascript
from DataFlow::MethodCallNode call
select call, call.analyze().ppTypes()

View File

@@ -0,0 +1,4 @@
| method-calls.js:25:11:25:21 | {m: f1}.m() | method-calls.js:26:2:26:3 | v1 | method-calls.js:24:23:24:24 | object literal |
| method-calls.js:30:11:30:16 | o2.m() | method-calls.js:31:2:31:3 | v2 | method-calls.js:28:23:28:24 | object literal |
| method-calls.js:34:11:34:23 | ({m: f3}).m() | method-calls.js:35:2:35:3 | v3 | method-calls.js:33:23:33:24 | object literal |
| method-calls.js:41:11:41:16 | o4.m() | method-calls.js:42:2:42:3 | v4 | file://:0:0:0:0 | indefinite value (call) |

View File

@@ -0,0 +1,5 @@
import javascript
from DataFlow::MethodCallNode call, DataFlow::Node use
where call.flowsTo(use) and use != call and not exists(use.getASuccessor())
select call, use, use.analyze().getAValue()

View File

@@ -0,0 +1,63 @@
(function() {
var o1 = {
m1: function(){ return {}; },
m2: function(){ return {}; },
m3: function(){ return {}; },
m4: function(){ return {}; }
};
o1.m1(); // analyzed precisely
o1.m2(); // analyzed precisely
unknown(o1.m2);
var o = unknown? o1: {};
o.m3(); // not analyzed precisely: `o1` is not the only receiver.
var m4 = o.m4;
m4(); // (not a method call)
var o2 = {};
o2.m = function() { return {}; };
// not analyzed precisely: `m` may be in the prototype since `m`
// is not in the initializer, and we do not attempt to reason flow
// sensitively beyond that at the moment
o2.m();
});
(function(){
function f1(){return {};}
var v1 = {m: f1}.m(); // analyzed precisely
v1 === true;
function f2(){return {};}
var o2 = {m: f2};
var v2 = o2.m(); // analyzed precisely
v2 === true;
function f3(){return {};}
var v3 = ({m: f3}).m(); // analyzed precisely
v3 === true;
function f4(){return {};}
var { o4 } = {m: f4};
// not analyzed precisely: o4 is from a destructuring assignment
// (and it is even `undefined` in this case)
var v4 = o4.m();
v4 === true;
});
(function(){
(function(o = {m: () => 42}){
var v1 = o.m(); // not analyzed precisely: `o` may be `unknown`
})(unknown);
function f(o = {m: () => 42}){
var v2 = o.m(); // not analyzed precisely: `o` may be `unknown`
};
f(unknown);
(function(o = {m: () => 42}){
var v3 = o.m(); // not analyzed precisely: `o.m` may be `unknown`
})({m: unknown});
(function(o = {m: () => 42}){
// not analyzed precisely: we only support unique receivers at
// the moment
var v4 = o.m();
})({m: () => true});
});

View File

@@ -0,0 +1,93 @@
(function capturedSource(){
let captured1 = {};
let captured2 = { f: function(){} };
let captured3 = { [unknown]: 42 };
unknown({});
function known(){}
known({});
function known_escaping(e){unknown(e)}
known_escaping({});
(function(){return {}});
(function(){throw {}});
global = {};
this.p = {};
let local_in_with;
with (unknown) {
local_in_with = {};
}
with({}){}
({ m: function(){ this; } });
({ m: unknown });
let indirectlyUnknown = unknown? unknown: function(){};
({ m: indirectlyUnknown });
});
(function capturedProperty(){
let captured1 = { p: 42 };
captured1.p;
captured1.p;
let captured2 = { p: 42, q: 42 };
captured2.p;
captured2.p;
captured2.q = 42;
captured2 = 42;
let nonObject = function(){}
nonObject.p = 42;
nonObject.p;
let nonInitializer = {};
nonInitializer.p = 42;
nonInitializer.p;
let overridden1 = { p: 42, p: 42 };
overridden1.p;
let overridden2 = { p: 42 };
overridden2.p = 42;
overridden2.p;
let overridden3 = { p: 42 };
overridden3[x] = 42;
overridden3.p;
function f(o) {
let captured3 = { p: 42 };
o = o || captured3;
o.p;
}
let captured4 = { };
captured4.p;
let captured5 = { p: 42 },
captured6 = { p: true };
(unknown? captured5: captured6).p; // could support this with a bit of extra work
(function(semiCaptured7){
if(unknown)
semiCaptured7 = {};
semiCaptured7.p = 42;
});
});
(function (){
let bound = {};
bound::unknown();
});
// semmle-extractor-options: --experimental

View File

@@ -0,0 +1,6 @@
class C {
constructor(
private readonly F: { timeout: number } = { timeout: 1500 }
) {
}
}

View File

@@ -2,6 +2,10 @@
| classes.ts:4:3:4:24 | instanc ... foo(); |
| classes.ts:8:3:8:39 | constru ... eld) {} |
| classes.ts:8:15:8:35 | public ... erField |
| classes.ts:12:5:12:68 | constru ... + 42; } |
| classes.ts:12:17:12:37 | public ... erField |
| classes.ts:16:5:16:46 | constru ... {}) {} |
| classes.ts:16:17:16:37 | public ... erField |
| tst.js:3:5:3:8 | x: 4 |
| tst.js:4:5:6:5 | func: f ... ;\\n } |
| tst.js:7:5:9:5 | f() {\\n ... ;\\n } |

View File

@@ -1,5 +1,7 @@
| classes.ts:4:3:4:24 | instanc ... foo(); | classes.ts:3:21:3:20 | this |
| classes.ts:8:15:8:35 | public ... erField | classes.ts:8:3:8:2 | this |
| classes.ts:12:17:12:37 | public ... erField | classes.ts:12:5:12:4 | this |
| classes.ts:16:17:16:37 | public ... erField | classes.ts:16:5:16:4 | this |
| tst.js:3:5:3:8 | x: 4 | tst.js:2:11:10:1 | {\\n x ... }\\n} |
| tst.js:4:5:6:5 | func: f ... ;\\n } | tst.js:2:11:10:1 | {\\n x ... }\\n} |
| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | tst.js:2:11:10:1 | {\\n x ... }\\n} |

View File

@@ -2,6 +2,10 @@
| classes.ts:4:3:4:24 | instanc ... foo(); | instanceField |
| classes.ts:8:3:8:39 | constru ... eld) {} | constructor |
| classes.ts:8:15:8:35 | public ... erField | parameterField |
| classes.ts:12:5:12:68 | constru ... + 42; } | constructor |
| classes.ts:12:17:12:37 | public ... erField | parameterField |
| classes.ts:16:5:16:46 | constru ... {}) {} | constructor |
| classes.ts:16:17:16:37 | public ... erField | parameterField |
| tst.js:3:5:3:8 | x: 4 | x |
| tst.js:4:5:6:5 | func: f ... ;\\n } | func |
| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | f |

View File

@@ -2,6 +2,11 @@
| classes.ts:4:3:4:24 | instanc ... foo(); | classes.ts:4:19:4:23 | foo() |
| classes.ts:8:3:8:39 | constru ... eld) {} | classes.ts:8:3:8:39 | constru ... eld) {} |
| classes.ts:8:15:8:35 | public ... erField | classes.ts:8:22:8:35 | parameterField |
| classes.ts:12:5:12:68 | constru ... + 42; } | classes.ts:12:5:12:68 | constru ... + 42; } |
| classes.ts:12:17:12:37 | public ... erField | classes.ts:12:24:12:37 | parameterField |
| classes.ts:16:5:16:46 | constru ... {}) {} | classes.ts:16:5:16:46 | constru ... {}) {} |
| classes.ts:16:17:16:37 | public ... erField | classes.ts:16:24:16:37 | parameterField |
| classes.ts:16:17:16:37 | public ... erField | classes.ts:16:41:16:42 | {} |
| tst.js:3:5:3:8 | x: 4 | tst.js:3:8:3:8 | 4 |
| tst.js:4:5:6:5 | func: f ... ;\\n } | tst.js:4:11:6:5 | functio ... ;\\n } |
| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | tst.js:7:6:9:5 | () {\\n ... ;\\n } |

View File

@@ -7,3 +7,11 @@ class InstanceField {
class ParameterField {
constructor(public parameterField) {}
}
class ParameterFieldInit {
constructor(public parameterField = {}) { parameterField + 42; }
}
class ParameterFieldInitUnused {
constructor(public parameterField = {}) {}
}

View File

@@ -1,5 +1,7 @@
| classes.ts:3:21:3:20 | this | classes.ts:4:3:4:24 | instanc ... foo(); |
| classes.ts:8:3:8:2 | this | classes.ts:8:15:8:35 | public ... erField |
| classes.ts:12:5:12:4 | this | classes.ts:12:17:12:37 | public ... erField |
| classes.ts:16:5:16:4 | this | classes.ts:16:17:16:37 | public ... erField |
| tst.js:1:1:1:0 | this | tst.js:23:15:23:29 | this.someMethod |
| tst.js:1:1:1:0 | this | tst.js:24:36:24:45 | this.state |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:3:5:3:8 | x: 4 |

View File

@@ -1,5 +1,7 @@
| classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:3:4:24 | instanc ... foo(); |
| classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:15:8:35 | public ... erField |
| classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:17:12:37 | public ... erField |
| classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:17:16:37 | public ... erField |
| tst.js:1:1:1:0 | this | someMethod | tst.js:23:15:23:29 | this.someMethod |
| tst.js:1:1:1:0 | this | state | tst.js:24:36:24:45 | this.state |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:5:9:5 | f() {\\n ... ;\\n } |

View File

@@ -1,5 +1,9 @@
| classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:19:4:23 | foo() |
| classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:22:8:35 | parameterField |
| classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:24:12:37 | parameterField |
| classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:41:12:42 | {} |
| classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:24:16:37 | parameterField |
| classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:41:16:42 | {} |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:6:9:5 | () {\\n ... ;\\n } |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:11:6:5 | functio ... ;\\n } |
| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:14:15:3 | (x) {\\n ... x);\\n } |

View File

@@ -1,5 +1,7 @@
| classes.ts:3:21:3:20 | this | classes.ts:4:3:4:24 | instanc ... foo(); |
| classes.ts:8:3:8:2 | this | classes.ts:8:15:8:35 | public ... erField |
| classes.ts:12:5:12:4 | this | classes.ts:12:17:12:37 | public ... erField |
| classes.ts:16:5:16:4 | this | classes.ts:16:17:16:37 | public ... erField |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:3:5:3:8 | x: 4 |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:4:5:6:5 | func: f ... ;\\n } |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:7:5:9:5 | f() {\\n ... ;\\n } |

View File

@@ -1,5 +1,7 @@
| classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:3:4:24 | instanc ... foo(); |
| classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:15:8:35 | public ... erField |
| classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:17:12:37 | public ... erField |
| classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:17:16:37 | public ... erField |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:5:9:5 | f() {\\n ... ;\\n } |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:5:6:5 | func: f ... ;\\n } |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | x | tst.js:3:5:3:8 | x: 4 |

View File

@@ -1,5 +1,8 @@
| classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:19:4:23 | foo() |
| classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:22:8:35 | parameterField |
| classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:24:12:37 | parameterField |
| classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:24:16:37 | parameterField |
| classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:41:16:42 | {} |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:6:9:5 | () {\\n ... ;\\n } |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:11:6:5 | functio ... ;\\n } |
| tst.js:2:11:10:1 | {\\n x ... }\\n} | x | tst.js:3:8:3:8 | 4 |

View File

@@ -1,3 +1,5 @@
| tst.js:5:7:5:19 | A.endsWith(B) | tst.js:5:7:5:7 | A | tst.js:5:18:5:18 | B | true |
| tst.js:6:7:6:22 | _.endsWith(A, B) | tst.js:6:18:6:18 | A | tst.js:6:21:6:21 | B | true |
| tst.js:7:7:7:22 | R.endsWith(A, B) | tst.js:7:18:7:18 | A | tst.js:7:21:7:21 | B | true |
| tst.js:6:7:6:19 | A.endsWith(B) | tst.js:6:7:6:7 | A | tst.js:6:18:6:18 | B | true |
| tst.js:7:7:7:22 | _.endsWith(A, B) | tst.js:7:18:7:18 | A | tst.js:7:21:7:21 | B | true |
| tst.js:8:7:8:22 | R.endsWith(A, B) | tst.js:8:18:8:18 | A | tst.js:8:21:8:21 | B | true |
| tst.js:9:7:9:28 | strings ... h(A, B) | tst.js:9:24:9:24 | A | tst.js:9:27:9:27 | B | true |
| tst.js:10:7:10:43 | strings ... h(A, B) | tst.js:10:39:10:39 | A | tst.js:10:42:10:42 | B | true |

View File

@@ -1,8 +1,11 @@
import * as _ from 'underscore';
import * as R from 'ramda';
let strings = goog.require('goog.string');
function test() {
if (A.endsWith(B)) {}
if (_.endsWith(A, B)) {}
if (R.endsWith(A, B)) {}
if (strings.endsWith(A, B)) {}
if (strings.caseInsensitiveEndsWith(A, B)) {}
}

View File

@@ -1,7 +1,9 @@
| tst.js:4:7:4:19 | A.includes(B) | tst.js:4:7:4:7 | A | tst.js:4:18:4:18 | B | true |
| tst.js:5:7:5:22 | _.includes(A, B) | tst.js:5:18:5:18 | A | tst.js:5:21:5:21 | B | true |
| tst.js:6:7:6:25 | A.indexOf(B) !== -1 | tst.js:6:7:6:7 | A | tst.js:6:17:6:17 | B | true |
| tst.js:7:7:7:23 | A.indexOf(B) >= 0 | tst.js:7:7:7:7 | A | tst.js:7:17:7:17 | B | true |
| tst.js:8:7:8:19 | ~A.indexOf(B) | tst.js:8:8:8:8 | A | tst.js:8:18:8:18 | B | true |
| tst.js:11:7:11:25 | A.indexOf(B) === -1 | tst.js:11:7:11:7 | A | tst.js:11:17:11:17 | B | false |
| tst.js:12:7:12:22 | A.indexOf(B) < 0 | tst.js:12:7:12:7 | A | tst.js:12:17:12:17 | B | false |
| tst.js:5:7:5:19 | A.includes(B) | tst.js:5:7:5:7 | A | tst.js:5:18:5:18 | B | true |
| tst.js:6:7:6:22 | _.includes(A, B) | tst.js:6:18:6:18 | A | tst.js:6:21:6:21 | B | true |
| tst.js:7:7:7:25 | A.indexOf(B) !== -1 | tst.js:7:7:7:7 | A | tst.js:7:17:7:17 | B | true |
| tst.js:8:7:8:23 | A.indexOf(B) >= 0 | tst.js:8:7:8:7 | A | tst.js:8:17:8:17 | B | true |
| tst.js:9:7:9:19 | ~A.indexOf(B) | tst.js:9:8:9:8 | A | tst.js:9:18:9:18 | B | true |
| tst.js:12:7:12:25 | A.indexOf(B) === -1 | tst.js:12:7:12:7 | A | tst.js:12:17:12:17 | B | false |
| tst.js:13:7:13:22 | A.indexOf(B) < 0 | tst.js:13:7:13:7 | A | tst.js:13:17:13:17 | B | false |
| tst.js:20:7:20:28 | strings ... s(A, B) | tst.js:20:24:20:24 | A | tst.js:20:27:20:27 | B | true |
| tst.js:21:7:21:43 | strings ... s(A, B) | tst.js:21:39:21:39 | A | tst.js:21:42:21:42 | B | true |

View File

@@ -1,4 +1,5 @@
import * as _ from 'lodash';
let strings = goog.require('goog.string');
function test() {
if (A.includes(B)) {}
@@ -15,4 +16,7 @@ function test() {
if (A.indexOf(B) === 0) {}
if (A.indexOf(B) !== 0) {}
if (A.indexOf(B) > 0) {}
if (strings.contains(A, B)) {}
if (strings.caseInsensitiveContains(A, B)) {}
}

View File

@@ -1,14 +1,16 @@
| tst.js:5:9:5:23 | A.startsWith(B) | tst.js:5:9:5:9 | A | tst.js:5:22:5:22 | B | true |
| tst.js:6:9:6:26 | _.startsWith(A, B) | tst.js:6:22:6:22 | A | tst.js:6:25:6:25 | B | true |
| tst.js:7:9:7:26 | R.startsWith(A, B) | tst.js:7:22:7:22 | A | tst.js:7:25:7:25 | B | true |
| tst.js:8:9:8:26 | A.indexOf(B) === 0 | tst.js:8:9:8:9 | A | tst.js:8:19:8:19 | B | true |
| tst.js:9:9:9:26 | A.indexOf(B) !== 0 | tst.js:9:9:9:9 | A | tst.js:9:19:9:19 | B | false |
| tst.js:10:9:10:26 | 0 !== A.indexOf(B) | tst.js:10:15:10:15 | A | tst.js:10:25:10:25 | B | false |
| tst.js:11:9:11:25 | 0 != A.indexOf(B) | tst.js:11:14:11:14 | A | tst.js:11:24:11:24 | B | false |
| tst.js:12:9:12:20 | A.indexOf(B) | tst.js:12:9:12:9 | A | tst.js:12:19:12:19 | B | false |
| tst.js:13:10:13:21 | A.indexOf(B) | tst.js:13:10:13:10 | A | tst.js:13:20:13:20 | B | false |
| tst.js:14:11:14:22 | A.indexOf(B) | tst.js:14:11:14:11 | A | tst.js:14:21:14:21 | B | false |
| tst.js:15:9:15:38 | A.subst ... ) === B | tst.js:15:9:15:9 | A | tst.js:15:38:15:38 | B | true |
| tst.js:16:9:16:38 | A.subst ... ) !== B | tst.js:16:9:16:9 | A | tst.js:16:38:16:38 | B | false |
| tst.js:17:9:17:35 | A.subst ... ) === B | tst.js:17:9:17:9 | A | tst.js:17:35:17:35 | B | true |
| tst.js:18:9:18:36 | A.subst ... "web/" | tst.js:18:9:18:9 | A | tst.js:18:31:18:36 | "web/" | true |
| tst.js:6:9:6:23 | A.startsWith(B) | tst.js:6:9:6:9 | A | tst.js:6:22:6:22 | B | true |
| tst.js:7:9:7:26 | _.startsWith(A, B) | tst.js:7:22:7:22 | A | tst.js:7:25:7:25 | B | true |
| tst.js:8:9:8:26 | R.startsWith(A, B) | tst.js:8:22:8:22 | A | tst.js:8:25:8:25 | B | true |
| tst.js:9:9:9:26 | A.indexOf(B) === 0 | tst.js:9:9:9:9 | A | tst.js:9:19:9:19 | B | true |
| tst.js:10:9:10:26 | A.indexOf(B) !== 0 | tst.js:10:9:10:9 | A | tst.js:10:19:10:19 | B | false |
| tst.js:11:9:11:26 | 0 !== A.indexOf(B) | tst.js:11:15:11:15 | A | tst.js:11:25:11:25 | B | false |
| tst.js:12:9:12:25 | 0 != A.indexOf(B) | tst.js:12:14:12:14 | A | tst.js:12:24:12:24 | B | false |
| tst.js:13:9:13:20 | A.indexOf(B) | tst.js:13:9:13:9 | A | tst.js:13:19:13:19 | B | false |
| tst.js:14:10:14:21 | A.indexOf(B) | tst.js:14:10:14:10 | A | tst.js:14:20:14:20 | B | false |
| tst.js:15:11:15:22 | A.indexOf(B) | tst.js:15:11:15:11 | A | tst.js:15:21:15:21 | B | false |
| tst.js:16:9:16:38 | A.subst ... ) === B | tst.js:16:9:16:9 | A | tst.js:16:38:16:38 | B | true |
| tst.js:17:9:17:38 | A.subst ... ) !== B | tst.js:17:9:17:9 | A | tst.js:17:38:17:38 | B | false |
| tst.js:18:9:18:35 | A.subst ... ) === B | tst.js:18:9:18:9 | A | tst.js:18:35:18:35 | B | true |
| tst.js:19:9:19:36 | A.subst ... "web/" | tst.js:19:9:19:9 | A | tst.js:19:31:19:36 | "web/" | true |
| tst.js:32:9:32:32 | strings ... h(A, B) | tst.js:32:28:32:28 | A | tst.js:32:31:32:31 | B | true |
| tst.js:33:9:33:47 | strings ... h(A, B) | tst.js:33:43:33:43 | A | tst.js:33:46:33:46 | B | true |

View File

@@ -1,5 +1,6 @@
import * as _ from 'lodash';
import * as R from 'ramda';
let strings = goog.require('goog.string');
function f(A, B) {
if (A.startsWith(B)) {}
@@ -27,4 +28,7 @@ function f(A, B) {
if (A.indexOf(B, 2)) {}
if (~A.indexOf(B)) {} // checks for existence, not startsWith
if (A.substring(B.length) === 0) {}
if (strings.startsWith(A, B)) {}
if (strings.caseInsensitiveStartsWith(A, B)) {}
}

View File

@@ -7,6 +7,7 @@
| tst.js:11:5:11:8 | f1() | file://:0:0:0:0 | undefined |
| tst.js:14:5:14:8 | f2() | file://:0:0:0:0 | undefined |
| tst.js:15:5:15:8 | f2() | file://:0:0:0:0 | undefined |
| tst.js:18:5:18:11 | o1.f3() | file://:0:0:0:0 | undefined |
| tst.js:23:5:23:8 | f4() | tst.js:21:16:21:30 | function f5 |
| tst.js:23:5:23:10 | f4()() | file://:0:0:0:0 | undefined |
| tst.js:30:5:30:8 | f6() | tst.js:26:16:28:9 | function f7 |

View File

@@ -11,7 +11,7 @@
| tst.js:11:5:11:8 | f1() | file://:0:0:0:0 | undefined |
| tst.js:14:5:14:8 | f2() | file://:0:0:0:0 | undefined |
| tst.js:15:5:15:8 | f2() | file://:0:0:0:0 | undefined |
| tst.js:18:5:18:11 | o1.f3() | file://:0:0:0:0 | indefinite value (call) |
| tst.js:18:5:18:11 | o1.f3() | file://:0:0:0:0 | undefined |
| tst.js:23:5:23:8 | f4() | tst.js:21:16:21:30 | function f5 |
| tst.js:23:5:23:10 | f4()() | file://:0:0:0:0 | undefined |
| tst.js:30:5:30:8 | f6() | tst.js:26:16:28:9 | function f7 |