@coana-tech/cli 14.12.79 → 14.12.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.mjs +5747 -5743
- package/package.json +1 -1
- package/reachability-analyzers-cli.mjs +1 -1
- package/repos/coana-tech/alucard/alucard.jar +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/cli.mjs +728 -879
- package/repos/coana-tech/goana/bin/goana-darwin-amd64.gz +0 -0
- package/repos/coana-tech/goana/bin/goana-darwin-arm64.gz +0 -0
- package/repos/coana-tech/goana/bin/goana-linux-amd64.gz +0 -0
- package/repos/coana-tech/goana/bin/goana-linux-arm64.gz +0 -0
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/src/parser.c +0 -471247
- package/repos/coana-tech/callgraph-reachability-analyzers/packages/cli/dist/bundle/node_modules/tree-sitter-ruby/tree-sitter-ruby.wasm +0 -0
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { createRequire } from 'module'; const require = createRequire(import.meta.url);
|
|
2
|
-
const __dirname = import.meta.dirname
|
|
3
|
-
const __filename = import.meta.filename
|
|
4
2
|
var __create = Object.create;
|
|
5
3
|
var __defProp = Object.defineProperty;
|
|
6
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -20911,12 +20909,10 @@ if (Number.parseInt(process.versions.node, 10) < 22) {
|
|
|
20911
20909
|
next: { value: next, writable: true, configurable: true }
|
|
20912
20910
|
});
|
|
20913
20911
|
};
|
|
20914
|
-
iteratorImpl2 = iteratorImpl;
|
|
20915
20912
|
class It {
|
|
20916
20913
|
[Symbol.iterator]() {
|
|
20917
20914
|
return this;
|
|
20918
20915
|
}
|
|
20919
|
-
// Iterator.prototype.map
|
|
20920
20916
|
map(fn) {
|
|
20921
20917
|
const iterator = this;
|
|
20922
20918
|
let index = 0;
|
|
@@ -20927,7 +20923,6 @@ if (Number.parseInt(process.versions.node, 10) < 22) {
|
|
|
20927
20923
|
return { value: fn(result.value, index++), done: false };
|
|
20928
20924
|
});
|
|
20929
20925
|
}
|
|
20930
|
-
// Iterator.prototype.filter
|
|
20931
20926
|
filter(fn) {
|
|
20932
20927
|
const iterator = this;
|
|
20933
20928
|
let index = 0;
|
|
@@ -20941,7 +20936,6 @@ if (Number.parseInt(process.versions.node, 10) < 22) {
|
|
|
20941
20936
|
}
|
|
20942
20937
|
});
|
|
20943
20938
|
}
|
|
20944
|
-
// Iterator.prototype.take
|
|
20945
20939
|
take(n12) {
|
|
20946
20940
|
const iterator = this;
|
|
20947
20941
|
let count = 0;
|
|
@@ -20952,7 +20946,6 @@ if (Number.parseInt(process.versions.node, 10) < 22) {
|
|
|
20952
20946
|
return iterator.next();
|
|
20953
20947
|
});
|
|
20954
20948
|
}
|
|
20955
|
-
// Iterator.prototype.drop
|
|
20956
20949
|
drop(n12) {
|
|
20957
20950
|
const iterator = this;
|
|
20958
20951
|
let count = 0;
|
|
@@ -20966,7 +20959,6 @@ if (Number.parseInt(process.versions.node, 10) < 22) {
|
|
|
20966
20959
|
return iterator.next();
|
|
20967
20960
|
});
|
|
20968
20961
|
}
|
|
20969
|
-
// Iterator.prototype.toArray
|
|
20970
20962
|
toArray() {
|
|
20971
20963
|
const result = [];
|
|
20972
20964
|
let next = this.next();
|
|
@@ -20976,13 +20968,11 @@ if (Number.parseInt(process.versions.node, 10) < 22) {
|
|
|
20976
20968
|
}
|
|
20977
20969
|
return result;
|
|
20978
20970
|
}
|
|
20979
|
-
// Iterator.prototype.forEach
|
|
20980
20971
|
forEach(fn) {
|
|
20981
20972
|
let index = 0;
|
|
20982
20973
|
for (const value of this)
|
|
20983
20974
|
fn(value, index++);
|
|
20984
20975
|
}
|
|
20985
|
-
// Iterator.prototype.some
|
|
20986
20976
|
some(fn) {
|
|
20987
20977
|
let index = 0;
|
|
20988
20978
|
for (const value of this)
|
|
@@ -20990,7 +20980,6 @@ if (Number.parseInt(process.versions.node, 10) < 22) {
|
|
|
20990
20980
|
return true;
|
|
20991
20981
|
return false;
|
|
20992
20982
|
}
|
|
20993
|
-
// Iterator.prototype.every
|
|
20994
20983
|
every(fn) {
|
|
20995
20984
|
let index = 0;
|
|
20996
20985
|
for (const value of this)
|
|
@@ -20998,14 +20987,12 @@ if (Number.parseInt(process.versions.node, 10) < 22) {
|
|
|
20998
20987
|
return false;
|
|
20999
20988
|
return true;
|
|
21000
20989
|
}
|
|
21001
|
-
// Iterator.prototype.find
|
|
21002
20990
|
find(fn) {
|
|
21003
20991
|
let index = 0;
|
|
21004
20992
|
for (const value of this)
|
|
21005
20993
|
if (fn(value, index++))
|
|
21006
20994
|
return value;
|
|
21007
20995
|
}
|
|
21008
|
-
// Iterator.prototype.reduce
|
|
21009
20996
|
reduce(fn, initialValue) {
|
|
21010
20997
|
let accumulator = initialValue;
|
|
21011
20998
|
let index = 0;
|
|
@@ -21020,7 +21007,6 @@ if (Number.parseInt(process.versions.node, 10) < 22) {
|
|
|
21020
21007
|
throw new TypeError("Reduce of empty iterator with no initial value");
|
|
21021
21008
|
return accumulator;
|
|
21022
21009
|
}
|
|
21023
|
-
// Iterator.prototype.flatMap
|
|
21024
21010
|
flatMap(fn) {
|
|
21025
21011
|
const iterator = this;
|
|
21026
21012
|
let currentIterator;
|
|
@@ -21045,7 +21031,6 @@ if (Number.parseInt(process.versions.node, 10) < 22) {
|
|
|
21045
21031
|
}
|
|
21046
21032
|
});
|
|
21047
21033
|
}
|
|
21048
|
-
// Iterator.from
|
|
21049
21034
|
static from(value) {
|
|
21050
21035
|
if (value === void 0)
|
|
21051
21036
|
throw new TypeError("Iterator.from requires a value");
|
|
@@ -21084,7 +21069,6 @@ if (Number.parseInt(process.versions.node, 10) < 22) {
|
|
|
21084
21069
|
Object.setPrototypeOf(proto, It.prototype);
|
|
21085
21070
|
}
|
|
21086
21071
|
}
|
|
21087
|
-
var iteratorImpl2;
|
|
21088
21072
|
|
|
21089
21073
|
// ../../node_modules/.pnpm/commander@14.0.2/node_modules/commander/esm.mjs
|
|
21090
21074
|
var import_index = __toESM(require_commander(), 1);
|
|
@@ -21277,7 +21261,7 @@ function n11(e5, t15) {
|
|
|
21277
21261
|
}
|
|
21278
21262
|
var r2 = (n12, { preserveConsecutiveUppercase: r3 = true } = {}) => t13(t14.test(n12) ? n12 : n12.toLowerCase()).map((e5, t15) => `${t15 === 0 ? e5[0].toLowerCase() : e5[0].toUpperCase()}${r3 ? e5.slice(1) : e5.slice(1).toLowerCase()}`).join(``);
|
|
21279
21263
|
|
|
21280
|
-
// ../utils/
|
|
21264
|
+
// ../utils/dist/asserts.js
|
|
21281
21265
|
import { format } from "node:util";
|
|
21282
21266
|
function assertDefined(value, msg, ...params) {
|
|
21283
21267
|
if (value === void 0 || value === null)
|
|
@@ -21285,7 +21269,7 @@ function assertDefined(value, msg, ...params) {
|
|
|
21285
21269
|
return value;
|
|
21286
21270
|
}
|
|
21287
21271
|
|
|
21288
|
-
// ../utils/
|
|
21272
|
+
// ../utils/dist/collections.js
|
|
21289
21273
|
function getOrSet(m, k, v) {
|
|
21290
21274
|
let r3 = m.get(k);
|
|
21291
21275
|
if (r3 === void 0) {
|
|
@@ -21346,7 +21330,8 @@ var Queue = class {
|
|
|
21346
21330
|
}
|
|
21347
21331
|
pop() {
|
|
21348
21332
|
if (this.items.length === 0) {
|
|
21349
|
-
if (this.back.length === 0)
|
|
21333
|
+
if (this.back.length === 0)
|
|
21334
|
+
throw new Error("Queue is empty");
|
|
21350
21335
|
[this.items, this.back] = [this.back.reverse(), this.items];
|
|
21351
21336
|
}
|
|
21352
21337
|
return this.items.pop();
|
|
@@ -21362,31 +21347,25 @@ var Queue = class {
|
|
|
21362
21347
|
}
|
|
21363
21348
|
};
|
|
21364
21349
|
|
|
21365
|
-
// ../utils/
|
|
21350
|
+
// ../utils/dist/logger.js
|
|
21366
21351
|
var import_winston = __toESM(require_winston(), 1);
|
|
21367
21352
|
import { tmpdir } from "node:os";
|
|
21368
21353
|
import { sep } from "node:path";
|
|
21369
21354
|
var logger = (0, import_winston.createLogger)({
|
|
21370
21355
|
level: "info",
|
|
21371
|
-
format: import_winston.format.combine(
|
|
21372
|
-
import_winston.format.splat(),
|
|
21373
|
-
import_winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss.SSS" }),
|
|
21374
|
-
...process.stdout.isTTY ? [import_winston.format.colorize()] : [],
|
|
21375
|
-
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
21376
|
-
import_winston.format.printf(({ level, message, label, timestamp }) => `${timestamp} ${label ?? "-"} ${level}: ${message}`)
|
|
21377
|
-
),
|
|
21356
|
+
format: import_winston.format.combine(import_winston.format.splat(), import_winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss.SSS" }), ...process.stdout.isTTY ? [import_winston.format.colorize()] : [], import_winston.format.printf(({ level, message, label, timestamp }) => `${timestamp} ${label ?? "-"} ${level}: ${message}`)),
|
|
21378
21357
|
transports: [new import_winston.default.transports.Console()]
|
|
21379
21358
|
});
|
|
21380
21359
|
function setLogLevel(level) {
|
|
21381
21360
|
logger.level = level;
|
|
21382
21361
|
}
|
|
21383
21362
|
|
|
21384
|
-
// ../utils/
|
|
21363
|
+
// ../utils/dist/numbers.js
|
|
21385
21364
|
function percent(part, total) {
|
|
21386
21365
|
return `${Math.round(part / (total || 1) * 1e4) / 100}%`;
|
|
21387
21366
|
}
|
|
21388
21367
|
|
|
21389
|
-
// ../utils/
|
|
21368
|
+
// ../utils/dist/source-locations.js
|
|
21390
21369
|
function locationToString(location, { filename = true } = {}) {
|
|
21391
21370
|
return `${filename ? `${location.filename}:` : ""}${location.start.line}:${location.start.column}:${location.end.line}:${location.end.column}`;
|
|
21392
21371
|
}
|
|
@@ -21398,7 +21377,7 @@ function createDummyLocation(filepath) {
|
|
|
21398
21377
|
};
|
|
21399
21378
|
}
|
|
21400
21379
|
|
|
21401
|
-
// ../utils/
|
|
21380
|
+
// ../utils/dist/tree-sitter-ast-utils.js
|
|
21402
21381
|
import assert2 from "node:assert";
|
|
21403
21382
|
var PRINT_NODES = !!process.env["PRINT_NODES"];
|
|
21404
21383
|
function visit(rootNode, astVisitor) {
|
|
@@ -21415,13 +21394,17 @@ function visit(rootNode, astVisitor) {
|
|
|
21415
21394
|
const gen = visitor(cursor.currentNode);
|
|
21416
21395
|
if (gen !== void 0) {
|
|
21417
21396
|
visitChildren = false;
|
|
21418
|
-
for (const child of gen)
|
|
21397
|
+
for (const child of gen)
|
|
21398
|
+
visitNode(child);
|
|
21419
21399
|
}
|
|
21420
21400
|
}
|
|
21421
|
-
if (visitChildren && cursor.gotoFirstChild())
|
|
21401
|
+
if (visitChildren && cursor.gotoFirstChild())
|
|
21402
|
+
continue;
|
|
21422
21403
|
while (true) {
|
|
21423
|
-
if (cursor.gotoNextSibling())
|
|
21424
|
-
|
|
21404
|
+
if (cursor.gotoNextSibling())
|
|
21405
|
+
break;
|
|
21406
|
+
if (!cursor.gotoParent())
|
|
21407
|
+
return;
|
|
21425
21408
|
}
|
|
21426
21409
|
}
|
|
21427
21410
|
}
|
|
@@ -21460,7 +21443,9 @@ function nodeEq(a, b) {
|
|
|
21460
21443
|
var NodeMap = class {
|
|
21461
21444
|
map = /* @__PURE__ */ new Map();
|
|
21462
21445
|
constructor(iterable) {
|
|
21463
|
-
if (iterable !== void 0)
|
|
21446
|
+
if (iterable !== void 0)
|
|
21447
|
+
for (const [key, value] of iterable)
|
|
21448
|
+
this.set(key, value);
|
|
21464
21449
|
}
|
|
21465
21450
|
get size() {
|
|
21466
21451
|
return this.map.size;
|
|
@@ -21515,16 +21500,19 @@ var FullNodeMap = class {
|
|
|
21515
21500
|
return this.entries();
|
|
21516
21501
|
}
|
|
21517
21502
|
forEach(callbackfn, thisArg) {
|
|
21518
|
-
for (const [key, value] of this)
|
|
21503
|
+
for (const [key, value] of this)
|
|
21504
|
+
callbackfn.call(thisArg, value, key, this);
|
|
21519
21505
|
}
|
|
21520
21506
|
entries() {
|
|
21521
21507
|
return this.map.values();
|
|
21522
21508
|
}
|
|
21523
21509
|
*keys() {
|
|
21524
|
-
for (const [key] of this)
|
|
21510
|
+
for (const [key] of this)
|
|
21511
|
+
yield key;
|
|
21525
21512
|
}
|
|
21526
21513
|
*values() {
|
|
21527
|
-
for (const [, value] of this)
|
|
21514
|
+
for (const [, value] of this)
|
|
21515
|
+
yield value;
|
|
21528
21516
|
}
|
|
21529
21517
|
};
|
|
21530
21518
|
var NodeSet = class {
|
|
@@ -21553,25 +21541,30 @@ var NodeSet = class {
|
|
|
21553
21541
|
[Symbol.toStringTag] = "NodeSet";
|
|
21554
21542
|
};
|
|
21555
21543
|
|
|
21556
|
-
// ../analysis-engine/
|
|
21544
|
+
// ../analysis-engine/dist/infos.js
|
|
21557
21545
|
import { join } from "node:path";
|
|
21558
21546
|
var PackageInfo = class {
|
|
21559
|
-
|
|
21560
|
-
|
|
21547
|
+
name;
|
|
21548
|
+
version;
|
|
21549
|
+
dir;
|
|
21550
|
+
isEntry;
|
|
21551
|
+
modules = /* @__PURE__ */ new Map();
|
|
21561
21552
|
constructor(name, version, dir, isEntry) {
|
|
21562
21553
|
this.name = name;
|
|
21563
21554
|
this.version = version;
|
|
21564
21555
|
this.dir = dir;
|
|
21565
21556
|
this.isEntry = isEntry;
|
|
21566
21557
|
}
|
|
21567
|
-
modules = /* @__PURE__ */ new Map();
|
|
21568
21558
|
toString() {
|
|
21569
21559
|
return `${this.name}${this.version ? `@${this.version}` : ""}`;
|
|
21570
21560
|
}
|
|
21571
21561
|
};
|
|
21572
21562
|
var ModuleInfo = class {
|
|
21573
|
-
|
|
21574
|
-
|
|
21563
|
+
relativePath;
|
|
21564
|
+
packageInfo;
|
|
21565
|
+
isEntry;
|
|
21566
|
+
isIncluded;
|
|
21567
|
+
loc;
|
|
21575
21568
|
constructor(relativePath, packageInfo, isEntry, isIncluded) {
|
|
21576
21569
|
this.relativePath = relativePath;
|
|
21577
21570
|
this.packageInfo = packageInfo;
|
|
@@ -21579,29 +21572,19 @@ var ModuleInfo = class {
|
|
|
21579
21572
|
this.isIncluded = isIncluded;
|
|
21580
21573
|
this.loc = createDummyLocation(this.getPath());
|
|
21581
21574
|
}
|
|
21582
|
-
// readonly functions = new Set<FunctionInfo>(); // functions directly inside this module
|
|
21583
|
-
loc;
|
|
21584
21575
|
toString() {
|
|
21585
21576
|
return `${this.packageInfo}:${this.relativePath}`;
|
|
21586
21577
|
}
|
|
21587
|
-
/**
|
|
21588
|
-
* Returns normalized file path of the representative file (different paths may refer to the same ModuleInfo).
|
|
21589
|
-
*/
|
|
21590
21578
|
getPath() {
|
|
21591
21579
|
return join(this.packageInfo.dir, this.relativePath);
|
|
21592
21580
|
}
|
|
21593
|
-
/**
|
|
21594
|
-
* Returns the official name of this module, using the package name if the module is the main module,
|
|
21595
|
-
* and otherwise stripping /index.js, .js and .mjs.
|
|
21596
|
-
*/
|
|
21597
|
-
/*
|
|
21598
|
-
getOfficialName(): string {
|
|
21599
|
-
if (this.relativePath === this.packageInfo.main) return this.packageInfo.name;
|
|
21600
|
-
return normalizeModuleName(`${this.packageInfo.name}/${this.relativePath}`);
|
|
21601
|
-
}
|
|
21602
|
-
*/
|
|
21603
21581
|
};
|
|
21604
21582
|
var FunctionInfo = class {
|
|
21583
|
+
name;
|
|
21584
|
+
node;
|
|
21585
|
+
parent;
|
|
21586
|
+
moduleInfo;
|
|
21587
|
+
loc;
|
|
21605
21588
|
constructor(name, node, parent, moduleInfo) {
|
|
21606
21589
|
this.name = name;
|
|
21607
21590
|
this.node = node;
|
|
@@ -21609,8 +21592,6 @@ var FunctionInfo = class {
|
|
|
21609
21592
|
this.moduleInfo = moduleInfo;
|
|
21610
21593
|
this.loc = getSourceLocation(node);
|
|
21611
21594
|
}
|
|
21612
|
-
// readonly functions = new Set<FunctionInfo>(); // functions directly inside this function
|
|
21613
|
-
loc;
|
|
21614
21595
|
get isEntry() {
|
|
21615
21596
|
return this.moduleInfo.isEntry;
|
|
21616
21597
|
}
|
|
@@ -21622,23 +21603,11 @@ var FunctionInfo = class {
|
|
|
21622
21603
|
}
|
|
21623
21604
|
};
|
|
21624
21605
|
|
|
21625
|
-
// ../analysis-engine/
|
|
21606
|
+
// ../analysis-engine/dist/call-graph.js
|
|
21626
21607
|
var CallGraph = class {
|
|
21627
|
-
/**
|
|
21628
|
-
* Map that provides for each function/module the set of functions that may be called.
|
|
21629
|
-
*/
|
|
21630
21608
|
functionToFunction = /* @__PURE__ */ new Map();
|
|
21631
|
-
/**
|
|
21632
|
-
* Map that provides for each call-site the set of functions that may be called.
|
|
21633
|
-
*/
|
|
21634
21609
|
callToFunctionOrModule = new FullNodeMap();
|
|
21635
|
-
/**
|
|
21636
|
-
* Map that provides for each call-site the innermost function that contains it.
|
|
21637
|
-
*/
|
|
21638
21610
|
callToContainingFunction = new NodeMap();
|
|
21639
|
-
/**
|
|
21640
|
-
* Adds an edge in the call graph (both function->function and call->function).
|
|
21641
|
-
*/
|
|
21642
21611
|
addEdge(call, from, to) {
|
|
21643
21612
|
const fs4 = mapGetSet(this.functionToFunction, from);
|
|
21644
21613
|
fs4.add(to);
|
|
@@ -21654,12 +21623,9 @@ var CallGraph = class {
|
|
|
21654
21623
|
return this.callToFunctionOrModule.entries().flatMap(([call, tos]) => {
|
|
21655
21624
|
const from = assertDefined(this.callToContainingFunction.get(call));
|
|
21656
21625
|
const loc = locationToString(from.loc);
|
|
21657
|
-
return tos.keys().map(
|
|
21658
|
-
(to) => `${loc} ${locationToString(getSourceLocation(call), { filename: false })} -> ${locationToString(to.loc)}`
|
|
21659
|
-
);
|
|
21626
|
+
return tos.keys().map((to) => `${loc} ${locationToString(getSourceLocation(call), { filename: false })} -> ${locationToString(to.loc)}`);
|
|
21660
21627
|
}).toArray();
|
|
21661
21628
|
}
|
|
21662
|
-
// Returns a parent map for all reachable functions starting from `initial`
|
|
21663
21629
|
reachableFunctions(initial) {
|
|
21664
21630
|
const stack = [...initial];
|
|
21665
21631
|
const parent = new Map(stack.map((f) => [f, void 0]));
|
|
@@ -21676,7 +21642,8 @@ var CallGraph = class {
|
|
|
21676
21642
|
serialize() {
|
|
21677
21643
|
const targetIndex = /* @__PURE__ */ new Map();
|
|
21678
21644
|
for (const f of [...this.functionToFunction.keys(), ...this.functionToFunction.values().flatMap(e3())]) {
|
|
21679
|
-
if (targetIndex.has(f))
|
|
21645
|
+
if (targetIndex.has(f))
|
|
21646
|
+
continue;
|
|
21680
21647
|
targetIndex.set(f, targetIndex.size);
|
|
21681
21648
|
}
|
|
21682
21649
|
const edgeIndex = /* @__PURE__ */ new Map();
|
|
@@ -21736,14 +21703,7 @@ function compareStaticWithDynamicCG(callGraph, moduleInfos, { targets, edges },
|
|
|
21736
21703
|
staticLibReachable
|
|
21737
21704
|
};
|
|
21738
21705
|
}
|
|
21739
|
-
function comparisonReport({
|
|
21740
|
-
dynamicEdges,
|
|
21741
|
-
dynamicReachable,
|
|
21742
|
-
dynamicLibReachable,
|
|
21743
|
-
staticEdges,
|
|
21744
|
-
staticReachable,
|
|
21745
|
-
staticLibReachable
|
|
21746
|
-
}) {
|
|
21706
|
+
function comparisonReport({ dynamicEdges, dynamicReachable, dynamicLibReachable, staticEdges, staticReachable, staticLibReachable }) {
|
|
21747
21707
|
const sse = new Set(staticEdges);
|
|
21748
21708
|
const ssr = new Set(staticReachable);
|
|
21749
21709
|
const sslr = new Set(staticLibReachable);
|
|
@@ -21764,13 +21724,13 @@ Extra: ${fmt(staticReachable.length - reachableMatches, staticReachable.length)}
|
|
|
21764
21724
|
`;
|
|
21765
21725
|
}
|
|
21766
21726
|
|
|
21767
|
-
// ../ruby-analyzer/
|
|
21727
|
+
// ../ruby-analyzer/dist/ruby-analyzer.js
|
|
21768
21728
|
import assert9 from "node:assert";
|
|
21769
21729
|
import { createReadStream } from "node:fs";
|
|
21770
21730
|
import { readFile } from "node:fs/promises";
|
|
21771
21731
|
import { basename as basename2, dirname as dirname3, resolve as resolve2 } from "node:path";
|
|
21772
21732
|
|
|
21773
|
-
// ../utils/
|
|
21733
|
+
// ../utils/dist/files.js
|
|
21774
21734
|
import { access, readdir, stat } from "node:fs/promises";
|
|
21775
21735
|
import { resolve } from "node:path";
|
|
21776
21736
|
async function findFiles(dir, predicate, recurse = e2(true)) {
|
|
@@ -21780,32 +21740,33 @@ async function findFiles(dir, predicate, recurse = e2(true)) {
|
|
|
21780
21740
|
for (const entry of entries) {
|
|
21781
21741
|
const fullPath = resolve(dir2, entry.name);
|
|
21782
21742
|
const e5 = entry.isSymbolicLink() ? await stat(fullPath) : entry;
|
|
21783
|
-
if (e5.isDirectory() && recurse(fullPath))
|
|
21784
|
-
|
|
21743
|
+
if (e5.isDirectory() && recurse(fullPath))
|
|
21744
|
+
await aux(fullPath);
|
|
21745
|
+
else if (e5.isFile() && await predicate(fullPath))
|
|
21746
|
+
files.push(fullPath);
|
|
21785
21747
|
}
|
|
21786
21748
|
};
|
|
21787
21749
|
await aux(dir);
|
|
21788
21750
|
return files;
|
|
21789
21751
|
}
|
|
21790
21752
|
|
|
21791
|
-
// ../utils/
|
|
21753
|
+
// ../utils/dist/timer.js
|
|
21792
21754
|
var Timer = class {
|
|
21755
|
+
timeout;
|
|
21756
|
+
startTime;
|
|
21793
21757
|
constructor(timeout) {
|
|
21794
21758
|
this.timeout = timeout;
|
|
21795
21759
|
this.reset();
|
|
21796
21760
|
}
|
|
21797
|
-
startTime;
|
|
21798
21761
|
reset() {
|
|
21799
21762
|
this.startTime = process.hrtime.bigint();
|
|
21800
21763
|
}
|
|
21801
|
-
/**
|
|
21802
|
-
* Returns the elapsed time in nanoseconds since the timer was created.
|
|
21803
|
-
*/
|
|
21804
21764
|
elapsed() {
|
|
21805
21765
|
return process.hrtime.bigint() - this.startTime;
|
|
21806
21766
|
}
|
|
21807
21767
|
checkTimeout() {
|
|
21808
|
-
if (this.timeout && this.elapsed() > BigInt(this.timeout) * 1000000000n)
|
|
21768
|
+
if (this.timeout && this.elapsed() > BigInt(this.timeout) * 1000000000n)
|
|
21769
|
+
throw new TimeoutException();
|
|
21809
21770
|
}
|
|
21810
21771
|
};
|
|
21811
21772
|
var TimeoutException = class extends Error {
|
|
@@ -21817,12 +21778,14 @@ function nanoToMs(n12) {
|
|
|
21817
21778
|
return `${n12 / 1000000n}ms`;
|
|
21818
21779
|
}
|
|
21819
21780
|
|
|
21820
|
-
// ../analysis-engine/
|
|
21781
|
+
// ../analysis-engine/dist/abstract-constraintvar.js
|
|
21821
21782
|
var ConstraintVar = class {
|
|
21822
21783
|
};
|
|
21823
21784
|
|
|
21824
|
-
// ../ruby-analyzer/
|
|
21785
|
+
// ../ruby-analyzer/dist/constraintvars.js
|
|
21825
21786
|
var NodeVar = class extends ConstraintVar {
|
|
21787
|
+
node;
|
|
21788
|
+
kind;
|
|
21826
21789
|
constructor(node, kind) {
|
|
21827
21790
|
super();
|
|
21828
21791
|
this.node = node;
|
|
@@ -21833,6 +21796,8 @@ var NodeVar = class extends ConstraintVar {
|
|
|
21833
21796
|
}
|
|
21834
21797
|
};
|
|
21835
21798
|
var MethodsVar = class extends ConstraintVar {
|
|
21799
|
+
obj;
|
|
21800
|
+
name;
|
|
21836
21801
|
constructor(obj, name) {
|
|
21837
21802
|
super();
|
|
21838
21803
|
this.obj = obj;
|
|
@@ -21843,6 +21808,7 @@ var MethodsVar = class extends ConstraintVar {
|
|
|
21843
21808
|
}
|
|
21844
21809
|
};
|
|
21845
21810
|
var AncestorsVar = class extends ConstraintVar {
|
|
21811
|
+
obj;
|
|
21846
21812
|
constructor(obj) {
|
|
21847
21813
|
super();
|
|
21848
21814
|
this.obj = obj;
|
|
@@ -21852,6 +21818,7 @@ var AncestorsVar = class extends ConstraintVar {
|
|
|
21852
21818
|
}
|
|
21853
21819
|
};
|
|
21854
21820
|
var ConstantVar = class extends ConstraintVar {
|
|
21821
|
+
constant;
|
|
21855
21822
|
constructor(constant) {
|
|
21856
21823
|
super();
|
|
21857
21824
|
this.constant = constant;
|
|
@@ -21861,6 +21828,8 @@ var ConstantVar = class extends ConstraintVar {
|
|
|
21861
21828
|
}
|
|
21862
21829
|
};
|
|
21863
21830
|
var ObjPropVar = class extends ConstraintVar {
|
|
21831
|
+
obj;
|
|
21832
|
+
prop;
|
|
21864
21833
|
constructor(obj, prop) {
|
|
21865
21834
|
super();
|
|
21866
21835
|
this.obj = obj;
|
|
@@ -21871,7 +21840,7 @@ var ObjPropVar = class extends ConstraintVar {
|
|
|
21871
21840
|
}
|
|
21872
21841
|
};
|
|
21873
21842
|
|
|
21874
|
-
// ../ruby-analyzer/
|
|
21843
|
+
// ../ruby-analyzer/dist/types/ruby-node-types.js
|
|
21875
21844
|
function isAliasNode(node) {
|
|
21876
21845
|
return node?.type === "alias";
|
|
21877
21846
|
}
|
|
@@ -21990,10 +21959,12 @@ function isStringContentNode(node) {
|
|
|
21990
21959
|
return node?.type === "string_content";
|
|
21991
21960
|
}
|
|
21992
21961
|
|
|
21993
|
-
// ../ruby-analyzer/
|
|
21962
|
+
// ../ruby-analyzer/dist/ruby-ast-helpers.js
|
|
21994
21963
|
function getStringContent(node) {
|
|
21995
|
-
if (node.namedChildCount === 0)
|
|
21996
|
-
|
|
21964
|
+
if (node.namedChildCount === 0)
|
|
21965
|
+
return "";
|
|
21966
|
+
else if (node.namedChildCount === 1 && isStringContentNode(node.namedChildren[0]))
|
|
21967
|
+
return node.namedChildren[0].text;
|
|
21997
21968
|
const parts = [];
|
|
21998
21969
|
for (const child of node.namedChildren)
|
|
21999
21970
|
switch (child.type) {
|
|
@@ -22015,59 +21986,56 @@ function getStringContent(node) {
|
|
|
22015
21986
|
}
|
|
22016
21987
|
function getLastNodeInFunction(node) {
|
|
22017
21988
|
const bodyNode = node.bodyNode;
|
|
22018
|
-
if (!bodyNode)
|
|
21989
|
+
if (!bodyNode)
|
|
21990
|
+
return;
|
|
22019
21991
|
const blockBodyNode = bodyNode.namedChildren.find((b) => b.type === "block_body");
|
|
22020
21992
|
return (blockBodyNode ?? bodyNode).lastNamedChild;
|
|
22021
21993
|
}
|
|
22022
21994
|
function isCommandCall(node, bindings) {
|
|
22023
|
-
if (bindings.has(node))
|
|
21995
|
+
if (bindings.has(node))
|
|
21996
|
+
return false;
|
|
22024
21997
|
const { parent } = node;
|
|
22025
|
-
if ((isMethodNode(parent) || isSingletonMethodNode(parent)) && parent.nameNode.id === node.id)
|
|
22026
|
-
|
|
22027
|
-
if (
|
|
21998
|
+
if ((isMethodNode(parent) || isSingletonMethodNode(parent)) && parent.nameNode.id === node.id)
|
|
21999
|
+
return false;
|
|
22000
|
+
if (isCallNode(parent) && parent.methodNode?.id === node.id)
|
|
22001
|
+
return false;
|
|
22002
|
+
if (isAliasNode(parent) && parent.namedChildren.some((c) => c.id === node.id))
|
|
22003
|
+
return false;
|
|
22028
22004
|
return true;
|
|
22029
22005
|
}
|
|
22030
22006
|
|
|
22031
|
-
// ../ruby-analyzer/
|
|
22007
|
+
// ../ruby-analyzer/dist/constraintvar-producer.js
|
|
22032
22008
|
var ConstraintVarProducer = class {
|
|
22033
|
-
|
|
22034
|
-
* Map from AST node to canonical NodeVar object - This ensures that we only have one constraint variable per AST node.
|
|
22035
|
-
*/
|
|
22036
|
-
canonicalNodeVars = t7(
|
|
22037
|
-
["normal", "callee", "return", "self", "default definee", "block param"],
|
|
22038
|
-
() => new NodeMap()
|
|
22039
|
-
);
|
|
22009
|
+
canonicalNodeVars = t7(["normal", "callee", "return", "self", "default definee", "block param"], () => new NodeMap());
|
|
22040
22010
|
canonicalMethodsVars = /* @__PURE__ */ new Map();
|
|
22041
22011
|
canonicalPropVars = /* @__PURE__ */ new Map();
|
|
22042
22012
|
canonicalAncestorsVars = /* @__PURE__ */ new WeakMap();
|
|
22043
22013
|
canonicalConstantVars = /* @__PURE__ */ new Map();
|
|
22044
|
-
/**
|
|
22045
|
-
* Map from constraint variable string hash to canonical ConstraintVar object.
|
|
22046
|
-
*/
|
|
22047
|
-
// private readonly canonicalConstraintVars = new Map<string, RubyConstraintVar>();
|
|
22048
22014
|
canonicalizeVar(v) {
|
|
22049
|
-
if (v instanceof NodeVar)
|
|
22015
|
+
if (v instanceof NodeVar)
|
|
22016
|
+
return getOrSet(this.canonicalNodeVars[v.kind], v.node, () => v);
|
|
22050
22017
|
else if (v instanceof MethodsVar) {
|
|
22051
22018
|
const map = getOrSet(this.canonicalMethodsVars, v.name, () => /* @__PURE__ */ new WeakMap());
|
|
22052
22019
|
return getOrSet(map, v.obj, () => v);
|
|
22053
22020
|
} else if (v instanceof ConstantVar)
|
|
22054
22021
|
return getOrSet(this.canonicalConstantVars, v.constant, () => v);
|
|
22055
|
-
else if (v instanceof AncestorsVar)
|
|
22022
|
+
else if (v instanceof AncestorsVar)
|
|
22023
|
+
return getOrSet(this.canonicalAncestorsVars, v.obj, () => v);
|
|
22056
22024
|
else if (v instanceof ObjPropVar) {
|
|
22057
22025
|
const map = getOrSet(this.canonicalPropVars, v.prop, () => /* @__PURE__ */ new WeakMap());
|
|
22058
22026
|
return getOrSet(map, v.obj, () => v);
|
|
22059
|
-
} else
|
|
22027
|
+
} else
|
|
22028
|
+
v;
|
|
22060
22029
|
throw new Error(`Unsupported constraint variable: ${v}`);
|
|
22061
22030
|
}
|
|
22062
22031
|
identVar(n12, bindings) {
|
|
22063
|
-
if (isCommandCall(n12, bindings))
|
|
22032
|
+
if (isCommandCall(n12, bindings))
|
|
22033
|
+
return this.nodeVar(n12);
|
|
22064
22034
|
const def = bindings.get(n12);
|
|
22065
|
-
if (!def)
|
|
22035
|
+
if (!def)
|
|
22036
|
+
logger.error(`No definition found for identifier: ${n12.text}`);
|
|
22066
22037
|
return this.nodeVar(def);
|
|
22067
22038
|
}
|
|
22068
|
-
/**
|
|
22069
|
-
* Finds the constraint variable representing the return values of the given function.
|
|
22070
|
-
*/
|
|
22071
22039
|
returnVar(fun) {
|
|
22072
22040
|
return this.canonicalizeVar(new NodeVar(fun, "return"));
|
|
22073
22041
|
}
|
|
@@ -22100,18 +22068,18 @@ var ConstraintVarProducer = class {
|
|
|
22100
22068
|
}
|
|
22101
22069
|
};
|
|
22102
22070
|
|
|
22103
|
-
// ../ruby-analyzer/
|
|
22071
|
+
// ../ruby-analyzer/dist/natives/native-builder.js
|
|
22104
22072
|
import assert6 from "node:assert";
|
|
22105
22073
|
|
|
22106
|
-
// ../ruby-analyzer/
|
|
22074
|
+
// ../ruby-analyzer/dist/tokens.js
|
|
22107
22075
|
import assert3 from "node:assert";
|
|
22108
22076
|
|
|
22109
|
-
// ../analysis-engine/
|
|
22077
|
+
// ../analysis-engine/dist/abstract-token.js
|
|
22110
22078
|
var TokenInterface = class {
|
|
22111
22079
|
hash;
|
|
22112
22080
|
};
|
|
22113
22081
|
|
|
22114
|
-
// ../utils/
|
|
22082
|
+
// ../utils/dist/strings.js
|
|
22115
22083
|
function strHash(s) {
|
|
22116
22084
|
let h1 = 0;
|
|
22117
22085
|
let h2 = 17656767856;
|
|
@@ -22127,7 +22095,7 @@ function strHash(s) {
|
|
|
22127
22095
|
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
|
|
22128
22096
|
}
|
|
22129
22097
|
|
|
22130
|
-
// ../ruby-analyzer/
|
|
22098
|
+
// ../ruby-analyzer/dist/tokens.js
|
|
22131
22099
|
function makeConstant(name) {
|
|
22132
22100
|
return name;
|
|
22133
22101
|
}
|
|
@@ -22145,25 +22113,17 @@ var TokenFactory = class {
|
|
|
22145
22113
|
canonicalMethodTokens = /* @__PURE__ */ new Map();
|
|
22146
22114
|
canonicalizeToken(token) {
|
|
22147
22115
|
if (token instanceof MethodToken) {
|
|
22148
|
-
const map = getOrSet(
|
|
22149
|
-
this.canonicalMethodTokens,
|
|
22150
|
-
token.methodName,
|
|
22151
|
-
() => /* @__PURE__ */ new WeakMap()
|
|
22152
|
-
);
|
|
22116
|
+
const map = getOrSet(this.canonicalMethodTokens, token.methodName, () => /* @__PURE__ */ new WeakMap());
|
|
22153
22117
|
return getOrSet(map, token.receiver, () => {
|
|
22154
22118
|
token.hash = strHash(`Method;${token.receiver};${token.methodName}`);
|
|
22155
22119
|
return token;
|
|
22156
22120
|
});
|
|
22157
22121
|
} else if (token instanceof ObjectToken) {
|
|
22158
|
-
const { index, ...maps } = getOrSet(
|
|
22159
|
-
this.canonicalObjectTokens,
|
|
22160
|
-
|
|
22161
|
-
|
|
22162
|
-
|
|
22163
|
-
nodeInstances: new NodeMap(),
|
|
22164
|
-
otherInstances: /* @__PURE__ */ new Map()
|
|
22165
|
-
})
|
|
22166
|
-
);
|
|
22122
|
+
const { index, ...maps } = getOrSet(this.canonicalObjectTokens, token.klass, () => ({
|
|
22123
|
+
index: this.canonicalObjectTokens.size,
|
|
22124
|
+
nodeInstances: new NodeMap(),
|
|
22125
|
+
otherInstances: /* @__PURE__ */ new Map()
|
|
22126
|
+
}));
|
|
22167
22127
|
const site = token instanceof SingletonClassToken ? token.obj : token.allocSite;
|
|
22168
22128
|
if (typeof site === "object" && "id" in site)
|
|
22169
22129
|
return getOrSet(maps.nodeInstances, site, () => {
|
|
@@ -22181,14 +22141,16 @@ var TokenFactory = class {
|
|
|
22181
22141
|
lambda: void 0
|
|
22182
22142
|
}));
|
|
22183
22143
|
const t15 = canon[token.kind] ??= token;
|
|
22184
|
-
if (t15 === token)
|
|
22144
|
+
if (t15 === token)
|
|
22145
|
+
t15.hash = strHash(`${token.kind};${syntaxNodeToHashStr(token.fun)}`);
|
|
22185
22146
|
return t15;
|
|
22186
22147
|
} else if (token instanceof NativeFunctionToken)
|
|
22187
22148
|
return getOrSet(this.canonicalNativeFunctionTokens, token.native, () => {
|
|
22188
22149
|
token.hash = strHash(token.native);
|
|
22189
22150
|
return token;
|
|
22190
22151
|
});
|
|
22191
|
-
else
|
|
22152
|
+
else
|
|
22153
|
+
token;
|
|
22192
22154
|
throw new Error(`Unknown token type: ${token}`);
|
|
22193
22155
|
}
|
|
22194
22156
|
createFunctionToken(fun, kind, scope, parameters = fun.parametersNode) {
|
|
@@ -22212,7 +22174,8 @@ var TokenFactory = class {
|
|
|
22212
22174
|
};
|
|
22213
22175
|
var ObjectToken = class extends TokenInterface {
|
|
22214
22176
|
constructor(key) {
|
|
22215
|
-
if (key !== tokenFactoryKey)
|
|
22177
|
+
if (key !== tokenFactoryKey)
|
|
22178
|
+
throw new Error("ObjectToken must be created through TokenFactory");
|
|
22216
22179
|
super();
|
|
22217
22180
|
}
|
|
22218
22181
|
isClassOrModuleToken() {
|
|
@@ -22223,6 +22186,7 @@ var ObjectToken = class extends TokenInterface {
|
|
|
22223
22186
|
}
|
|
22224
22187
|
};
|
|
22225
22188
|
var ClassToken = class extends ObjectToken {
|
|
22189
|
+
allocSite;
|
|
22226
22190
|
constructor(key, allocSite) {
|
|
22227
22191
|
super(key);
|
|
22228
22192
|
this.allocSite = allocSite;
|
|
@@ -22233,29 +22197,36 @@ var ClassToken = class extends ObjectToken {
|
|
|
22233
22197
|
};
|
|
22234
22198
|
var rubyClassToken = ClassToken.prototype.klass = new ClassToken(tokenFactoryKey, "::Class");
|
|
22235
22199
|
var SingletonClassToken = class extends ObjectToken {
|
|
22200
|
+
obj;
|
|
22201
|
+
static {
|
|
22202
|
+
this.prototype.klass = rubyClassToken;
|
|
22203
|
+
}
|
|
22236
22204
|
constructor(key, obj) {
|
|
22237
22205
|
super(key);
|
|
22238
22206
|
this.obj = obj;
|
|
22239
22207
|
}
|
|
22240
|
-
static {
|
|
22241
|
-
this.prototype.klass = rubyClassToken;
|
|
22242
|
-
}
|
|
22243
22208
|
toString() {
|
|
22244
22209
|
return `SingletonClass[${this.obj}]`;
|
|
22245
22210
|
}
|
|
22246
22211
|
};
|
|
22247
22212
|
var InstanceToken = class extends ObjectToken {
|
|
22213
|
+
klass;
|
|
22214
|
+
allocSite;
|
|
22248
22215
|
constructor(key, klass, allocSite) {
|
|
22249
22216
|
super(key);
|
|
22250
22217
|
this.klass = klass;
|
|
22251
22218
|
this.allocSite = allocSite;
|
|
22252
22219
|
}
|
|
22253
22220
|
toString() {
|
|
22254
|
-
if (this.allocSite === void 0)
|
|
22221
|
+
if (this.allocSite === void 0)
|
|
22222
|
+
return `Instance[${this.klass}]`;
|
|
22255
22223
|
return `Object[${typeof this.allocSite === "string" ? this.allocSite : `${this.allocSite.type}:${nodeLocationToString(this.allocSite)}`} < ${this.klass}]`;
|
|
22256
22224
|
}
|
|
22257
22225
|
};
|
|
22258
22226
|
var MethodToken = class extends ObjectToken {
|
|
22227
|
+
klass;
|
|
22228
|
+
receiver;
|
|
22229
|
+
methodName;
|
|
22259
22230
|
constructor(key, klass, receiver, methodName) {
|
|
22260
22231
|
super(key);
|
|
22261
22232
|
this.klass = klass;
|
|
@@ -22267,13 +22238,18 @@ var MethodToken = class extends ObjectToken {
|
|
|
22267
22238
|
}
|
|
22268
22239
|
};
|
|
22269
22240
|
var FunctionToken = class extends TokenInterface {
|
|
22241
|
+
fun;
|
|
22242
|
+
parameters;
|
|
22243
|
+
kind;
|
|
22244
|
+
scope;
|
|
22270
22245
|
constructor(key, fun, parameters, kind, scope) {
|
|
22271
22246
|
super();
|
|
22272
22247
|
this.fun = fun;
|
|
22273
22248
|
this.parameters = parameters;
|
|
22274
22249
|
this.kind = kind;
|
|
22275
22250
|
this.scope = scope;
|
|
22276
|
-
if (key !== tokenFactoryKey)
|
|
22251
|
+
if (key !== tokenFactoryKey)
|
|
22252
|
+
throw new Error("FunctionToken must be created through TokenFactory");
|
|
22277
22253
|
assert3(kind === "method" || isBlockNode(fun) || isDoBlockNode(fun));
|
|
22278
22254
|
}
|
|
22279
22255
|
toString() {
|
|
@@ -22281,31 +22257,33 @@ var FunctionToken = class extends TokenInterface {
|
|
|
22281
22257
|
return `${t2(this.kind)}[${repr}]`;
|
|
22282
22258
|
}
|
|
22283
22259
|
toKind(kind, { tokenFactory }) {
|
|
22284
|
-
if (this.kind === kind)
|
|
22260
|
+
if (this.kind === kind)
|
|
22261
|
+
return this;
|
|
22285
22262
|
return tokenFactory.createFunctionToken(this.fun, kind, this.scope, this.parameters);
|
|
22286
22263
|
}
|
|
22287
22264
|
};
|
|
22288
22265
|
var NativeFunctionToken = class extends TokenInterface {
|
|
22289
|
-
|
|
22266
|
+
native;
|
|
22267
|
+
invoke;
|
|
22290
22268
|
constructor(key, native, invoke) {
|
|
22291
22269
|
super();
|
|
22292
22270
|
this.native = native;
|
|
22293
22271
|
this.invoke = invoke;
|
|
22294
|
-
if (key !== tokenFactoryKey)
|
|
22272
|
+
if (key !== tokenFactoryKey)
|
|
22273
|
+
throw new Error("NativeObjectToken must be created through TokenFactory");
|
|
22295
22274
|
}
|
|
22296
22275
|
toString() {
|
|
22297
22276
|
return `NativeFunction[${this.native}]`;
|
|
22298
22277
|
}
|
|
22299
22278
|
};
|
|
22300
22279
|
|
|
22301
|
-
// ../utils/
|
|
22280
|
+
// ../utils/dist/objects.js
|
|
22302
22281
|
function maybeOmit(obj, key) {
|
|
22303
22282
|
return key in obj ? n7(obj, [key]) : obj;
|
|
22304
22283
|
}
|
|
22305
22284
|
|
|
22306
|
-
// ../ruby-analyzer/
|
|
22285
|
+
// ../ruby-analyzer/dist/natives/3rd-party/jwe.js
|
|
22307
22286
|
var jwe_default = {
|
|
22308
|
-
// TODO: Check whether these work for old versions
|
|
22309
22287
|
"JWE::Enc": {
|
|
22310
22288
|
fake: true,
|
|
22311
22289
|
staticMethods: {
|
|
@@ -22327,20 +22305,22 @@ var jwe_default = {
|
|
|
22327
22305
|
}
|
|
22328
22306
|
};
|
|
22329
22307
|
|
|
22330
|
-
// ../ruby-analyzer/
|
|
22308
|
+
// ../ruby-analyzer/dist/natives/models/module.js
|
|
22331
22309
|
import assert4 from "node:assert";
|
|
22332
22310
|
|
|
22333
|
-
// ../utils/
|
|
22311
|
+
// ../utils/dist/cache.js
|
|
22334
22312
|
function cache(func, map = /* @__PURE__ */ new Map()) {
|
|
22335
22313
|
return (key, ...rest) => {
|
|
22336
22314
|
let value = map.get(key);
|
|
22337
|
-
if (value === void 0)
|
|
22315
|
+
if (value === void 0)
|
|
22316
|
+
map.set(key, value = func(key, ...rest));
|
|
22338
22317
|
return value;
|
|
22339
22318
|
};
|
|
22340
22319
|
}
|
|
22341
22320
|
|
|
22342
|
-
// ../ruby-analyzer/
|
|
22343
|
-
var TokenListener
|
|
22321
|
+
// ../ruby-analyzer/dist/listeners.js
|
|
22322
|
+
var TokenListener;
|
|
22323
|
+
(function(TokenListener2) {
|
|
22344
22324
|
TokenListener2[TokenListener2["Call"] = 0] = "Call";
|
|
22345
22325
|
TokenListener2[TokenListener2["Method"] = 1] = "Method";
|
|
22346
22326
|
TokenListener2[TokenListener2["READ_BASE"] = 2] = "READ_BASE";
|
|
@@ -22369,10 +22349,9 @@ var TokenListener = /* @__PURE__ */ ((TokenListener2) => {
|
|
|
22369
22349
|
TokenListener2[TokenListener2["NATIVE_BASIC_OBJECT_INSTANCE_EXEC_PROC"] = 25] = "NATIVE_BASIC_OBJECT_INSTANCE_EXEC_PROC";
|
|
22370
22350
|
TokenListener2[TokenListener2["RAILS_INITIALIZABLE_INITIALIZER"] = 26] = "RAILS_INITIALIZABLE_INITIALIZER";
|
|
22371
22351
|
TokenListener2[TokenListener2["RAILS_INITIALIZABLE_INITIALIZER_PROC"] = 27] = "RAILS_INITIALIZABLE_INITIALIZER_PROC";
|
|
22372
|
-
|
|
22373
|
-
})(TokenListener || {});
|
|
22352
|
+
})(TokenListener || (TokenListener = {}));
|
|
22374
22353
|
|
|
22375
|
-
// ../ruby-analyzer/
|
|
22354
|
+
// ../ruby-analyzer/dist/natives/utils.js
|
|
22376
22355
|
function unsupported(klass, name) {
|
|
22377
22356
|
return ({ cd, op }) => {
|
|
22378
22357
|
op.a.warnUnsupported(cd.callNode, `Unsupported native method '${klass}#${name}'`);
|
|
@@ -22381,10 +22360,12 @@ function unsupported(klass, name) {
|
|
|
22381
22360
|
};
|
|
22382
22361
|
}
|
|
22383
22362
|
function literalArg(op, cd, arg, method) {
|
|
22384
|
-
if (!arg)
|
|
22363
|
+
if (!arg)
|
|
22364
|
+
op.a.warnUnsupported(cd.callNode, `${method} called with undefined (unsupported) argument`);
|
|
22385
22365
|
else if (arg instanceof ConstraintVar || arg instanceof TokenInterface)
|
|
22386
22366
|
op.a.warnUnsupported(cd.callNode, `${method} called with non-literal argument`);
|
|
22387
|
-
else
|
|
22367
|
+
else
|
|
22368
|
+
return arg;
|
|
22388
22369
|
}
|
|
22389
22370
|
function invokeBlock(block, listener, defaultDefinee, p) {
|
|
22390
22371
|
if (block) {
|
|
@@ -22392,25 +22373,24 @@ function invokeBlock(block, listener, defaultDefinee, p) {
|
|
|
22392
22373
|
const key = { t: base, n: cd.callNode };
|
|
22393
22374
|
op.addForAllTokensConstraint(block, listener, key, (t15) => {
|
|
22394
22375
|
if (t15 instanceof ObjectToken) {
|
|
22395
|
-
if (t15.klass !== op.state.globalNatives.Proc)
|
|
22396
|
-
|
|
22397
|
-
|
|
22398
|
-
|
|
22399
|
-
|
|
22400
|
-
|
|
22401
|
-
|
|
22402
|
-
|
|
22403
|
-
|
|
22404
|
-
|
|
22405
|
-
|
|
22406
|
-
|
|
22407
|
-
|
|
22408
|
-
} else t15;
|
|
22376
|
+
if (t15.klass !== op.state.globalNatives.Proc)
|
|
22377
|
+
return;
|
|
22378
|
+
op.solver.addForAllTokensConstraint(op.cvp.methodsVar(op.singletonClass(t15), "call"), listener + 1, key, (ft) => {
|
|
22379
|
+
if (ft instanceof FunctionToken) {
|
|
22380
|
+
op.inclusionConstraint(defaultDefinee, op.cvp.defaultDefineeVar(ft.fun));
|
|
22381
|
+
op.dispatchCall(ft.toKind("method", op), base, cd);
|
|
22382
|
+
} else if (ft instanceof NativeFunctionToken)
|
|
22383
|
+
ft.invoke(p);
|
|
22384
|
+
else
|
|
22385
|
+
ft;
|
|
22386
|
+
});
|
|
22387
|
+
} else
|
|
22388
|
+
t15;
|
|
22409
22389
|
});
|
|
22410
22390
|
}
|
|
22411
22391
|
}
|
|
22412
22392
|
|
|
22413
|
-
// ../ruby-analyzer/
|
|
22393
|
+
// ../ruby-analyzer/dist/natives/models/module.js
|
|
22414
22394
|
function include(kind, { base, op, cd }) {
|
|
22415
22395
|
if (base instanceof SingletonClassToken) {
|
|
22416
22396
|
op.a.warnUnsupported(cd.callNode, `Module#${kind} on a singleton class`);
|
|
@@ -22420,7 +22400,8 @@ function include(kind, { base, op, cd }) {
|
|
|
22420
22400
|
logger.error(`Module#${kind} is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`);
|
|
22421
22401
|
return;
|
|
22422
22402
|
}
|
|
22423
|
-
if (cd.arguments?.pSplat)
|
|
22403
|
+
if (cd.arguments?.pSplat)
|
|
22404
|
+
op.a.warnUnsupported(cd.callNode, `Module#${kind} called with splat arguments`);
|
|
22424
22405
|
const ncd = {
|
|
22425
22406
|
...cd,
|
|
22426
22407
|
arguments: { positional: [base] },
|
|
@@ -22428,46 +22409,44 @@ function include(kind, { base, op, cd }) {
|
|
|
22428
22409
|
};
|
|
22429
22410
|
for (const arg of cd.arguments?.positional ?? [])
|
|
22430
22411
|
if (arg instanceof ConstraintVar || arg instanceof ObjectToken)
|
|
22431
|
-
op.addForAllTokensConstraint(
|
|
22432
|
-
|
|
22433
|
-
|
|
22434
|
-
|
|
22435
|
-
|
|
22436
|
-
|
|
22437
|
-
|
|
22438
|
-
|
|
22439
|
-
|
|
22440
|
-
|
|
22441
|
-
|
|
22442
|
-
}
|
|
22443
|
-
);
|
|
22444
|
-
else arg;
|
|
22412
|
+
op.addForAllTokensConstraint(arg, TokenListener.NATIVE_MODULE_INCLUDE, { t: base, s: kind, n: cd.callNode }, (t15) => {
|
|
22413
|
+
if (t15 instanceof ObjectToken) {
|
|
22414
|
+
if (t15.klass === op.state.globalNatives.Module) {
|
|
22415
|
+
op.callMethod(t15, kind === "include" ? "append_features" : "prepend_features", ncd);
|
|
22416
|
+
op.callMethod(t15, kind === "include" ? "included" : "prepended", ncd);
|
|
22417
|
+
}
|
|
22418
|
+
} else
|
|
22419
|
+
t15;
|
|
22420
|
+
});
|
|
22421
|
+
else
|
|
22422
|
+
arg;
|
|
22445
22423
|
}
|
|
22446
22424
|
function appendFeatures({ base, op, cd }) {
|
|
22447
22425
|
assert4.strictEqual(base.klass, op.state.globalNatives.Module);
|
|
22448
|
-
if (cd.arguments?.pSplat)
|
|
22426
|
+
if (cd.arguments?.pSplat)
|
|
22427
|
+
op.a.warnUnsupported(cd.callNode, "Module#append_features called with splat arguments");
|
|
22449
22428
|
const srcAv = op.cvp.ancestorsVar(base);
|
|
22450
22429
|
for (const arg of cd.arguments?.positional ?? [])
|
|
22451
22430
|
if (arg instanceof ConstraintVar || arg instanceof ObjectToken)
|
|
22452
|
-
op.addForAllTokensConstraint(arg,
|
|
22431
|
+
op.addForAllTokensConstraint(arg, TokenListener.NATIVE_MODULE_APPEND_FEATURES, { t: base }, (t15) => {
|
|
22453
22432
|
if (t15 instanceof ObjectToken) {
|
|
22454
22433
|
if (t15 instanceof SingletonClassToken)
|
|
22455
22434
|
op.a.warnUnsupported(cd.callNode, "Module#append_features called with a singleton class");
|
|
22456
|
-
else if (t15.isClassOrModuleToken())
|
|
22435
|
+
else if (t15.isClassOrModuleToken())
|
|
22436
|
+
op.solver.addSubsetConstraint(srcAv, op.cvp.ancestorsVar(t15));
|
|
22457
22437
|
else
|
|
22458
|
-
throw new Error(
|
|
22459
|
-
|
|
22460
|
-
|
|
22461
|
-
} else t15;
|
|
22438
|
+
throw new Error(`Module#append_features is called with a non-Class or Module token ${t15} at ${nodeToString(cd.callNode)}`);
|
|
22439
|
+
} else
|
|
22440
|
+
t15;
|
|
22462
22441
|
});
|
|
22463
|
-
else
|
|
22442
|
+
else
|
|
22443
|
+
arg;
|
|
22464
22444
|
}
|
|
22465
22445
|
function attrModel(name, { base, op, cd }) {
|
|
22466
22446
|
if (!base.isClassLikeToken())
|
|
22467
|
-
throw new Error(
|
|
22468
|
-
|
|
22469
|
-
);
|
|
22470
|
-
if (cd.arguments?.pSplat) op.a.warnUnsupported(cd.callNode, `Module#attr_${name} called with splat arguments`);
|
|
22447
|
+
throw new Error(`Module#attr_${name} is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`);
|
|
22448
|
+
if (cd.arguments?.pSplat)
|
|
22449
|
+
op.a.warnUnsupported(cd.callNode, `Module#attr_${name} called with splat arguments`);
|
|
22471
22450
|
for (const arg of cd.arguments?.positional ?? []) {
|
|
22472
22451
|
const lArg = literalArg(op, cd, arg, `Module#attr_${name}`);
|
|
22473
22452
|
if (lArg) {
|
|
@@ -22478,15 +22457,9 @@ function attrModel(name, { base, op, cd }) {
|
|
|
22478
22457
|
}
|
|
22479
22458
|
function attrModelImpl(op, name, base, attr) {
|
|
22480
22459
|
if (name !== "writer")
|
|
22481
|
-
op.solver.addTokenConstraint(
|
|
22482
|
-
op.tokenFactory.createNativeFunctionToken(...attrReader(attr)),
|
|
22483
|
-
op.cvp.methodsVar(base, attr)
|
|
22484
|
-
);
|
|
22460
|
+
op.solver.addTokenConstraint(op.tokenFactory.createNativeFunctionToken(...attrReader(attr)), op.cvp.methodsVar(base, attr));
|
|
22485
22461
|
if (name !== "reader")
|
|
22486
|
-
op.solver.addTokenConstraint(
|
|
22487
|
-
op.tokenFactory.createNativeFunctionToken(...attrWriter(attr)),
|
|
22488
|
-
op.cvp.methodsVar(base, `${attr}=`)
|
|
22489
|
-
);
|
|
22462
|
+
op.solver.addTokenConstraint(op.tokenFactory.createNativeFunctionToken(...attrWriter(attr)), op.cvp.methodsVar(base, `${attr}=`));
|
|
22490
22463
|
}
|
|
22491
22464
|
var module_default = {
|
|
22492
22465
|
newInstance({ op, cd }) {
|
|
@@ -22499,28 +22472,24 @@ var module_default = {
|
|
|
22499
22472
|
prepend: include.bind(void 0, "prepend"),
|
|
22500
22473
|
alias_method({ op, base, cd }) {
|
|
22501
22474
|
if (!base.isClassLikeToken())
|
|
22502
|
-
throw new Error(
|
|
22503
|
-
|
|
22504
|
-
);
|
|
22505
|
-
if (cd.arguments?.pSplat) op.a.warnUnsupported(cd.callNode, "Module#alias_method called with splat arguments");
|
|
22475
|
+
throw new Error(`Module#alias_method is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`);
|
|
22476
|
+
if (cd.arguments?.pSplat)
|
|
22477
|
+
op.a.warnUnsupported(cd.callNode, "Module#alias_method called with splat arguments");
|
|
22506
22478
|
const pos = cd.arguments?.positional;
|
|
22507
22479
|
if (pos?.length !== 2) {
|
|
22508
22480
|
op.a.warnUnsupported(cd.callNode, "Module#alias_method called with incorrect number of positional arguments");
|
|
22509
22481
|
return;
|
|
22510
22482
|
}
|
|
22511
22483
|
const lArgs = pos.map((a) => literalArg(op, cd, a, "Module#alias_method"));
|
|
22512
|
-
if (lArgs.includes(void 0))
|
|
22513
|
-
|
|
22514
|
-
|
|
22515
|
-
);
|
|
22484
|
+
if (lArgs.includes(void 0))
|
|
22485
|
+
return;
|
|
22486
|
+
const [target, source] = lArgs.map((a) => a.type === "symbol" ? a.value.slice(1) : a.value);
|
|
22516
22487
|
op.solver.addSubsetConstraint(op.cvp.methodsVar(base, source), op.cvp.methodsVar(base, target));
|
|
22517
22488
|
},
|
|
22518
22489
|
define_method: unsupported("Module", "define_method"),
|
|
22519
22490
|
module_function({ op, base, cd }) {
|
|
22520
22491
|
if (!base.isClassLikeToken())
|
|
22521
|
-
throw new Error(
|
|
22522
|
-
`Module#module_function is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`
|
|
22523
|
-
);
|
|
22492
|
+
throw new Error(`Module#module_function is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`);
|
|
22524
22493
|
if (base.klass !== op.state.globalNatives.Module)
|
|
22525
22494
|
return;
|
|
22526
22495
|
if (isCallNode(cd.callNode) && cd.callNode.receiverNode && !isSelfNode(cd.callNode.receiverNode))
|
|
@@ -22528,7 +22497,8 @@ var module_default = {
|
|
|
22528
22497
|
const names = [];
|
|
22529
22498
|
if (!cd.arguments || !("pSplat" in cd.arguments || cd.arguments.positional?.length)) {
|
|
22530
22499
|
const scope = assertDefined(cd.callNode.closest(["block", "do_block", "module", "program"]));
|
|
22531
|
-
if (isModuleNode(scope))
|
|
22500
|
+
if (isModuleNode(scope))
|
|
22501
|
+
assert4(base.allocSite.endsWith(`::${scope.nameNode.text}`));
|
|
22532
22502
|
const endPos = cd.callNode.endPosition;
|
|
22533
22503
|
for (const [name, startPos] of DefinedMethodsVisitor.getNames(scope, op))
|
|
22534
22504
|
if (startPos.row > endPos.row || startPos.row === endPos.row && startPos.column >= endPos.column)
|
|
@@ -22538,7 +22508,8 @@ var module_default = {
|
|
|
22538
22508
|
op.a.warnUnsupported(cd.callNode, "Module#module_function called with splat arguments");
|
|
22539
22509
|
for (const arg of cd.arguments.positional ?? []) {
|
|
22540
22510
|
const lArg = literalArg(op, cd, arg, "Module#module_function");
|
|
22541
|
-
if (lArg)
|
|
22511
|
+
if (lArg)
|
|
22512
|
+
names.push(lArg.type === "symbol" ? lArg.value.slice(1) : lArg.value);
|
|
22542
22513
|
}
|
|
22543
22514
|
}
|
|
22544
22515
|
const sct = op.singletonClass(base);
|
|
@@ -22552,12 +22523,11 @@ var module_default = {
|
|
|
22552
22523
|
op.a.warnUnsupported(cd.callNode, "Module#const_get on a singleton class");
|
|
22553
22524
|
return;
|
|
22554
22525
|
} else if (!base.isClassOrModuleToken())
|
|
22555
|
-
throw new Error(
|
|
22556
|
-
`Module#const_get is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`
|
|
22557
|
-
);
|
|
22526
|
+
throw new Error(`Module#const_get is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`);
|
|
22558
22527
|
const positional = cd.arguments?.positional;
|
|
22559
22528
|
const lArg = literalArg(op, cd, positional?.[0], "Module#const_get");
|
|
22560
|
-
if (!lArg)
|
|
22529
|
+
if (!lArg)
|
|
22530
|
+
return;
|
|
22561
22531
|
const name = lArg.type === "symbol" ? lArg.value.slice(1) : lArg.value;
|
|
22562
22532
|
checkConstant(name);
|
|
22563
22533
|
if (name.startsWith("::")) {
|
|
@@ -22568,20 +22538,21 @@ var module_default = {
|
|
|
22568
22538
|
const vars = [];
|
|
22569
22539
|
if (inherit) {
|
|
22570
22540
|
vars.push(op.cvp.ancestorsVar(base));
|
|
22571
|
-
if (base.klass === op.state.globalNatives.Module)
|
|
22572
|
-
|
|
22541
|
+
if (base.klass === op.state.globalNatives.Module)
|
|
22542
|
+
vars.push(op.cvp.ancestorsVar(op.state.globalNatives.Object));
|
|
22543
|
+
} else
|
|
22544
|
+
vars.push(base);
|
|
22573
22545
|
for (const v of vars)
|
|
22574
|
-
op.addForAllTokensConstraint(v,
|
|
22546
|
+
op.addForAllTokensConstraint(v, TokenListener.NATIVE_MODULE_CONST_GET, { n: cd.callNode }, (t15) => {
|
|
22575
22547
|
if (t15 instanceof ObjectToken) {
|
|
22576
22548
|
if (t15 instanceof SingletonClassToken)
|
|
22577
22549
|
op.a.warnUnsupported(cd.callNode, "Module#const_get called with a singleton class ancestor");
|
|
22578
22550
|
else if (t15.isClassOrModuleToken())
|
|
22579
22551
|
op.solver.addSubsetConstraint(op.cvp.constantVar(makeConstant(`${t15.allocSite}::${name}`)), cd.result);
|
|
22580
22552
|
else
|
|
22581
|
-
throw new Error(
|
|
22582
|
-
|
|
22583
|
-
|
|
22584
|
-
} else t15;
|
|
22553
|
+
throw new Error(`Module#const_get is called with a non-Class or Module token ${t15} at ${nodeToString(cd.callNode)}`);
|
|
22554
|
+
} else
|
|
22555
|
+
t15;
|
|
22585
22556
|
});
|
|
22586
22557
|
},
|
|
22587
22558
|
const_set({ op, base, cd }) {
|
|
@@ -22589,19 +22560,21 @@ var module_default = {
|
|
|
22589
22560
|
op.a.warnUnsupported(cd.callNode, "Module#const_set on a singleton class");
|
|
22590
22561
|
return;
|
|
22591
22562
|
} else if (!base.isClassOrModuleToken())
|
|
22592
|
-
throw new Error(
|
|
22593
|
-
`Module#const_set is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`
|
|
22594
|
-
);
|
|
22563
|
+
throw new Error(`Module#const_set is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`);
|
|
22595
22564
|
const pos = cd.arguments?.positional;
|
|
22596
22565
|
const value = pos?.[1];
|
|
22597
|
-
if (!(value instanceof ConstraintVar || value instanceof TokenInterface))
|
|
22598
|
-
|
|
22566
|
+
if (!(value instanceof ConstraintVar || value instanceof TokenInterface))
|
|
22567
|
+
return;
|
|
22568
|
+
if (cd.result)
|
|
22569
|
+
op.inclusionConstraint(value, cd.result);
|
|
22599
22570
|
const lArg = literalArg(op, cd, pos[0], "Module#const_set");
|
|
22600
|
-
if (!lArg)
|
|
22571
|
+
if (!lArg)
|
|
22572
|
+
return;
|
|
22601
22573
|
const name = lArg.type === "symbol" ? lArg.value.slice(1) : lArg.value;
|
|
22602
22574
|
if (/^[A-Z][^:]*$/.test(name))
|
|
22603
22575
|
op.inclusionConstraint(value, op.cvp.constantVar(makeConstant(`${base.allocSite}::${name}`)));
|
|
22604
|
-
else
|
|
22576
|
+
else
|
|
22577
|
+
op.a.warnUnsupported(cd.callNode, "Module#const_set with invalid constant name");
|
|
22605
22578
|
},
|
|
22606
22579
|
attr: unsupported("Module", "attr"),
|
|
22607
22580
|
attr_reader: attrModel.bind(void 0, "reader"),
|
|
@@ -22609,9 +22582,7 @@ var module_default = {
|
|
|
22609
22582
|
attr_accessor: attrModel.bind(void 0, "accessor"),
|
|
22610
22583
|
module_eval({ op, base, cd }) {
|
|
22611
22584
|
if (!base.isClassLikeToken())
|
|
22612
|
-
throw new Error(
|
|
22613
|
-
`Module#module_eval is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`
|
|
22614
|
-
);
|
|
22585
|
+
throw new Error(`Module#module_eval is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`);
|
|
22615
22586
|
const pos = cd.arguments?.positional;
|
|
22616
22587
|
if (pos?.length) {
|
|
22617
22588
|
const a = pos[0];
|
|
@@ -22619,34 +22590,21 @@ var module_default = {
|
|
|
22619
22590
|
op.a.warnUnsupported(cd.callNode, "Module#module_eval with dynamically computed argument");
|
|
22620
22591
|
else if (a.type === "string")
|
|
22621
22592
|
op.a.warnUnsupported(cd.callNode, "Module#module_eval with statically known string argument");
|
|
22622
|
-
else
|
|
22593
|
+
else
|
|
22594
|
+
op.a.warnUnsupported(cd.callNode, `Module#module_eval with ${a.type} argument`);
|
|
22623
22595
|
return;
|
|
22624
22596
|
}
|
|
22625
|
-
invokeBlock(
|
|
22626
|
-
|
|
22627
|
-
13 /* NATIVE_MODULE_MODULE_EVAL */,
|
|
22628
|
-
// Functions defined in the block are defined on the module itself
|
|
22597
|
+
invokeBlock(cd.arguments?.block, TokenListener.NATIVE_MODULE_MODULE_EVAL, base, {
|
|
22598
|
+
op,
|
|
22629
22599
|
base,
|
|
22630
|
-
{
|
|
22631
|
-
|
|
22632
|
-
base,
|
|
22633
|
-
cd: { ...cd, arguments: { positional: [base] } }
|
|
22634
|
-
}
|
|
22635
|
-
);
|
|
22600
|
+
cd: { ...cd, arguments: { positional: [base] } }
|
|
22601
|
+
});
|
|
22636
22602
|
},
|
|
22637
22603
|
module_exec({ op, base, cd }) {
|
|
22638
22604
|
if (!base.isClassLikeToken())
|
|
22639
|
-
throw new Error(
|
|
22640
|
-
`Module#module_exec is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`
|
|
22641
|
-
);
|
|
22605
|
+
throw new Error(`Module#module_exec is called on a non-Class or Module token ${base} at ${nodeToString(cd.callNode)}`);
|
|
22642
22606
|
const { block, ...args } = cd.arguments ?? {};
|
|
22643
|
-
invokeBlock(
|
|
22644
|
-
block,
|
|
22645
|
-
15 /* NATIVE_MODULE_MODULE_EXEC */,
|
|
22646
|
-
// Functions defined in the block are defined on the module itself
|
|
22647
|
-
base,
|
|
22648
|
-
{ op, base, cd: { ...cd, arguments: args } }
|
|
22649
|
-
);
|
|
22607
|
+
invokeBlock(block, TokenListener.NATIVE_MODULE_MODULE_EXEC, base, { op, base, cd: { ...cd, arguments: args } });
|
|
22650
22608
|
},
|
|
22651
22609
|
using: unsupported("Module", "using")
|
|
22652
22610
|
},
|
|
@@ -22661,14 +22619,16 @@ var module_default = {
|
|
|
22661
22619
|
var attrReader = cache((name) => [
|
|
22662
22620
|
makeNative(`Module#attr_reader#${name}`),
|
|
22663
22621
|
({ op, cd, base }) => {
|
|
22664
|
-
if (!(base instanceof ObjectToken))
|
|
22622
|
+
if (!(base instanceof ObjectToken))
|
|
22623
|
+
throw new Error("attr_reader is called on a non-object");
|
|
22665
22624
|
op.solver.addSubsetConstraint(op.cvp.objPropVar(base, `@${name}`), cd.result);
|
|
22666
22625
|
}
|
|
22667
22626
|
]);
|
|
22668
22627
|
var attrWriter = cache((name) => [
|
|
22669
22628
|
makeNative(`Module#attr_writer#${name}`),
|
|
22670
22629
|
({ op, cd, base }) => {
|
|
22671
|
-
if (!(base instanceof ObjectToken))
|
|
22630
|
+
if (!(base instanceof ObjectToken))
|
|
22631
|
+
throw new Error("attr_writer is called on a non-object");
|
|
22672
22632
|
const positional = cd.arguments?.positional;
|
|
22673
22633
|
if (positional?.length !== 1) {
|
|
22674
22634
|
op.a.warnUnsupported(cd.callNode, "attr_writer called with incorrect number of positional arguments");
|
|
@@ -22676,27 +22636,31 @@ var attrWriter = cache((name) => [
|
|
|
22676
22636
|
}
|
|
22677
22637
|
const arg = positional[0];
|
|
22678
22638
|
const rVar = op.cvp.objPropVar(base, `@${name}`);
|
|
22679
|
-
if (arg instanceof ConstraintVar)
|
|
22680
|
-
|
|
22681
|
-
else arg
|
|
22639
|
+
if (arg instanceof ConstraintVar)
|
|
22640
|
+
op.solver.addSubsetConstraint(arg, rVar);
|
|
22641
|
+
else if (arg instanceof ObjectToken)
|
|
22642
|
+
op.solver.addTokenConstraint(arg, rVar);
|
|
22643
|
+
else
|
|
22644
|
+
arg;
|
|
22682
22645
|
}
|
|
22683
22646
|
]);
|
|
22684
22647
|
var DefinedMethodsVisitor = class _DefinedMethodsVisitor {
|
|
22648
|
+
op;
|
|
22649
|
+
static getNames = cache((scope, op) => {
|
|
22650
|
+
const visitor = new _DefinedMethodsVisitor(op);
|
|
22651
|
+
const v = visitor;
|
|
22652
|
+
if (isBlockNode(scope) || isDoBlockNode(scope) || isModuleNode(scope)) {
|
|
22653
|
+
if (scope.bodyNode)
|
|
22654
|
+
visit(scope.bodyNode, v);
|
|
22655
|
+
} else
|
|
22656
|
+
for (const node of scope.namedChildren)
|
|
22657
|
+
visit(node, v);
|
|
22658
|
+
return visitor.names;
|
|
22659
|
+
}, new NodeMap());
|
|
22660
|
+
names = new Array();
|
|
22685
22661
|
constructor(op) {
|
|
22686
22662
|
this.op = op;
|
|
22687
22663
|
}
|
|
22688
|
-
static getNames = cache(
|
|
22689
|
-
(scope, op) => {
|
|
22690
|
-
const visitor = new _DefinedMethodsVisitor(op);
|
|
22691
|
-
const v = visitor;
|
|
22692
|
-
if (isBlockNode(scope) || isDoBlockNode(scope) || isModuleNode(scope)) {
|
|
22693
|
-
if (scope.bodyNode) visit(scope.bodyNode, v);
|
|
22694
|
-
} else for (const node of scope.namedChildren) visit(node, v);
|
|
22695
|
-
return visitor.names;
|
|
22696
|
-
},
|
|
22697
|
-
new NodeMap()
|
|
22698
|
-
);
|
|
22699
|
-
names = new Array();
|
|
22700
22664
|
*method(node) {
|
|
22701
22665
|
this.names.push([node.nameNode.text, node.startPosition]);
|
|
22702
22666
|
}
|
|
@@ -22710,8 +22674,6 @@ var DefinedMethodsVisitor = class _DefinedMethodsVisitor {
|
|
|
22710
22674
|
}
|
|
22711
22675
|
}
|
|
22712
22676
|
}
|
|
22713
|
-
// Stop visitor from going into nested scopes
|
|
22714
|
-
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
22715
22677
|
*singleton_method() {
|
|
22716
22678
|
}
|
|
22717
22679
|
*block() {
|
|
@@ -22724,10 +22686,9 @@ var DefinedMethodsVisitor = class _DefinedMethodsVisitor {
|
|
|
22724
22686
|
}
|
|
22725
22687
|
*singleton_class() {
|
|
22726
22688
|
}
|
|
22727
|
-
/* eslint-enable @typescript-eslint/no-empty-function */
|
|
22728
22689
|
};
|
|
22729
22690
|
|
|
22730
|
-
// ../ruby-analyzer/
|
|
22691
|
+
// ../ruby-analyzer/dist/natives/3rd-party/nokogiri.js
|
|
22731
22692
|
var nokogiri_default = {
|
|
22732
22693
|
"Nokogiri::XML::Node": {
|
|
22733
22694
|
fake: true
|
|
@@ -22736,11 +22697,7 @@ var nokogiri_default = {
|
|
|
22736
22697
|
fake: true,
|
|
22737
22698
|
methods: {
|
|
22738
22699
|
initialize({ base, op }) {
|
|
22739
|
-
op.solver.addTokenConstraint(
|
|
22740
|
-
// eslint-disable-next-line unicorn/no-useless-undefined
|
|
22741
|
-
op.tokenFactory.createInstanceToken(op.state.globalNatives["Nokogiri::XML::Node"], void 0),
|
|
22742
|
-
op.cvp.objPropVar(base, "@root")
|
|
22743
|
-
);
|
|
22700
|
+
op.solver.addTokenConstraint(op.tokenFactory.createInstanceToken(op.state.globalNatives["Nokogiri::XML::Node"], void 0), op.cvp.objPropVar(base, "@root"));
|
|
22744
22701
|
}
|
|
22745
22702
|
},
|
|
22746
22703
|
setup(t15, op) {
|
|
@@ -22749,32 +22706,27 @@ var nokogiri_default = {
|
|
|
22749
22706
|
}
|
|
22750
22707
|
};
|
|
22751
22708
|
|
|
22752
|
-
// ../ruby-analyzer/
|
|
22709
|
+
// ../ruby-analyzer/dist/natives/3rd-party/rails.js
|
|
22753
22710
|
var rails_default = {
|
|
22754
22711
|
"Rails::Initializable::ClassMethods": {
|
|
22755
22712
|
fake: true,
|
|
22756
22713
|
methods: {
|
|
22757
22714
|
initializer({ base, op, cd }) {
|
|
22758
22715
|
const blk = cd.arguments?.block;
|
|
22759
|
-
if (!blk)
|
|
22716
|
+
if (!blk)
|
|
22717
|
+
return;
|
|
22760
22718
|
if (!(base instanceof ClassToken)) {
|
|
22761
22719
|
op.a.warnUnsupported(cd.callNode, "Rails::Initializable::ClassMethods#initializer called on non-Class");
|
|
22762
22720
|
return;
|
|
22763
22721
|
}
|
|
22764
22722
|
const it = op.tokenFactory.createInstanceToken(base, void 0);
|
|
22765
|
-
invokeBlock(
|
|
22766
|
-
blk,
|
|
22767
|
-
26 /* RAILS_INITIALIZABLE_INITIALIZER */,
|
|
22768
|
-
// uses instance_exec under the hood
|
|
22769
|
-
op.singletonClass(it),
|
|
22770
|
-
{ op, base: it, cd: n7(cd, ["arguments"]) }
|
|
22771
|
-
);
|
|
22723
|
+
invokeBlock(blk, TokenListener.RAILS_INITIALIZABLE_INITIALIZER, op.singletonClass(it), { op, base: it, cd: n7(cd, ["arguments"]) });
|
|
22772
22724
|
}
|
|
22773
22725
|
}
|
|
22774
22726
|
}
|
|
22775
22727
|
};
|
|
22776
22728
|
|
|
22777
|
-
// ../ruby-analyzer/
|
|
22729
|
+
// ../ruby-analyzer/dist/natives/models/basic-object.js
|
|
22778
22730
|
var basic_object_default = {
|
|
22779
22731
|
methods: {
|
|
22780
22732
|
instance_eval({ op, base, cd }) {
|
|
@@ -22785,10 +22737,11 @@ var basic_object_default = {
|
|
|
22785
22737
|
op.a.warnUnsupported(cd.callNode, "BasicObject#instance_eval with dynamically computed argument");
|
|
22786
22738
|
else if (a.type === "string")
|
|
22787
22739
|
op.a.warnUnsupported(cd.callNode, "BasicObject#instance_eval with statically known string argument");
|
|
22788
|
-
else
|
|
22740
|
+
else
|
|
22741
|
+
op.a.warnUnsupported(cd.callNode, `BasicObject#instance_eval with ${a.type} argument`);
|
|
22789
22742
|
return;
|
|
22790
22743
|
}
|
|
22791
|
-
invokeBlock(cd.arguments?.block,
|
|
22744
|
+
invokeBlock(cd.arguments?.block, TokenListener.NATIVE_BASIC_OBJECT_INSTANCE_EVAL, op.singletonClass(base), {
|
|
22792
22745
|
op,
|
|
22793
22746
|
base,
|
|
22794
22747
|
cd: { ...cd, arguments: { positional: [base] } }
|
|
@@ -22796,7 +22749,7 @@ var basic_object_default = {
|
|
|
22796
22749
|
},
|
|
22797
22750
|
instance_exec({ op, base, cd }) {
|
|
22798
22751
|
const { block, ...args } = cd.arguments ?? {};
|
|
22799
|
-
invokeBlock(block,
|
|
22752
|
+
invokeBlock(block, TokenListener.NATIVE_BASIC_OBJECT_INSTANCE_EXEC, op.singletonClass(base), {
|
|
22800
22753
|
op,
|
|
22801
22754
|
base,
|
|
22802
22755
|
cd: { ...cd, arguments: args }
|
|
@@ -22805,7 +22758,7 @@ var basic_object_default = {
|
|
|
22805
22758
|
}
|
|
22806
22759
|
};
|
|
22807
22760
|
|
|
22808
|
-
// ../ruby-analyzer/
|
|
22761
|
+
// ../ruby-analyzer/dist/natives/models/kernel.js
|
|
22809
22762
|
import assert5 from "node:assert";
|
|
22810
22763
|
import fs from "node:fs";
|
|
22811
22764
|
import { dirname, extname, isAbsolute, join as join2 } from "node:path";
|
|
@@ -22816,13 +22769,15 @@ function callProcNew(p) {
|
|
|
22816
22769
|
function simpleResolver(root) {
|
|
22817
22770
|
return (candidate) => {
|
|
22818
22771
|
const fullPath = join2(root, candidate);
|
|
22819
|
-
if (fs.existsSync(fullPath))
|
|
22772
|
+
if (fs.existsSync(fullPath))
|
|
22773
|
+
return fullPath;
|
|
22820
22774
|
};
|
|
22821
22775
|
}
|
|
22822
22776
|
var cachedResolver = cache((root) => {
|
|
22823
22777
|
const paths = new Set(globSync2(`**/*.{${requireExtensions.map((ext2) => ext2.slice(1)).join(",")}}`, { cwd: root }));
|
|
22824
22778
|
return (c) => {
|
|
22825
|
-
if (paths.has(c.startsWith("./") ? c.slice(2) : c))
|
|
22779
|
+
if (paths.has(c.startsWith("./") ? c.slice(2) : c))
|
|
22780
|
+
return join2(root, c);
|
|
22826
22781
|
};
|
|
22827
22782
|
});
|
|
22828
22783
|
function loadModule(method, required, roots, candidates, op, cd) {
|
|
@@ -22850,12 +22805,7 @@ function requireImpl(method, { op, cd }) {
|
|
|
22850
22805
|
const positional = cd.arguments?.positional;
|
|
22851
22806
|
const arg = positional?.[expectedArgs - 1];
|
|
22852
22807
|
if (positional?.length !== expectedArgs) {
|
|
22853
|
-
logger.error(
|
|
22854
|
-
"Kernel#%s called with wrong number of arguments (%d, expected %d)",
|
|
22855
|
-
method,
|
|
22856
|
-
positional?.length ?? 0,
|
|
22857
|
-
expectedArgs
|
|
22858
|
-
);
|
|
22808
|
+
logger.error("Kernel#%s called with wrong number of arguments (%d, expected %d)", method, positional?.length ?? 0, expectedArgs);
|
|
22859
22809
|
return;
|
|
22860
22810
|
} else if (!arg || arg instanceof ConstraintVar || arg instanceof TokenInterface || arg.type !== "string") {
|
|
22861
22811
|
op.a.warnUnsupported(cd.callNode, `Kernel#${method} called with non-constant string argument`);
|
|
@@ -22871,19 +22821,19 @@ function requireImpl(method, { op, cd }) {
|
|
|
22871
22821
|
if (isAbsolute(required)) {
|
|
22872
22822
|
op.a.warnUnsupported(cd.callNode, `Kernel#${method} called with absolute path: '${required}'`);
|
|
22873
22823
|
return;
|
|
22874
|
-
} else if (explicitlyRelative(required))
|
|
22875
|
-
|
|
22824
|
+
} else if (explicitlyRelative(required))
|
|
22825
|
+
requireFrom = [simpleResolver(op.a.rootDir)];
|
|
22826
|
+
else
|
|
22827
|
+
requireFrom = op.state.loadPath.map(cachedResolver);
|
|
22876
22828
|
}
|
|
22877
22829
|
loadModule(method, required, requireFrom, candidates, op, cd);
|
|
22878
22830
|
}
|
|
22879
22831
|
var globalKernelMethods = {
|
|
22880
22832
|
eval: unsupported("Kernel", "eval"),
|
|
22881
22833
|
proc: callProcNew,
|
|
22882
|
-
// FIXME: Tag the resulting Proc as a lambda
|
|
22883
22834
|
lambda: callProcNew,
|
|
22884
22835
|
require_relative: requireImpl.bind(void 0, "require_relative"),
|
|
22885
22836
|
require: requireImpl.bind(void 0, "require"),
|
|
22886
|
-
// Treat `autoload` is an immediate require, which is sound but (possibly) imprecise
|
|
22887
22837
|
autoload: requireImpl.bind(void 0, "autoload"),
|
|
22888
22838
|
load: ({ op, cd }) => {
|
|
22889
22839
|
const positional = cd.arguments?.positional;
|
|
@@ -22898,16 +22848,10 @@ var globalKernelMethods = {
|
|
|
22898
22848
|
if (positional.length >= 2 || cd.arguments?.keyword?.some(([name]) => name === "wrap"))
|
|
22899
22849
|
op.a.warnUnsupported(cd.callNode, "Kernel#load called with 'wrap' argument");
|
|
22900
22850
|
const required = arg.value;
|
|
22901
|
-
if (isAbsolute(required))
|
|
22851
|
+
if (isAbsolute(required))
|
|
22852
|
+
op.a.warnUnsupported(cd.callNode, `Kernel#load called with absolute path: '${required}'`);
|
|
22902
22853
|
else
|
|
22903
|
-
loadModule(
|
|
22904
|
-
"load",
|
|
22905
|
-
required,
|
|
22906
|
-
[...explicitlyRelative(required) ? [] : op.state.loadPath.map(cachedResolver), simpleResolver(op.a.rootDir)],
|
|
22907
|
-
[required],
|
|
22908
|
-
op,
|
|
22909
|
-
cd
|
|
22910
|
-
);
|
|
22854
|
+
loadModule("load", required, [...explicitlyRelative(required) ? [] : op.state.loadPath.map(cachedResolver), simpleResolver(op.a.rootDir)], [required], op, cd);
|
|
22911
22855
|
}
|
|
22912
22856
|
};
|
|
22913
22857
|
var kernel_default = {
|
|
@@ -22919,9 +22863,11 @@ var kernel_default = {
|
|
|
22919
22863
|
define_singleton_method({ base, op, cd }) {
|
|
22920
22864
|
let [nameArg, methodArg] = cd.arguments?.positional ?? [];
|
|
22921
22865
|
const lNameArg = literalArg(op, cd, nameArg, "Kernel#define_singleton_method");
|
|
22922
|
-
if (!lNameArg)
|
|
22866
|
+
if (!lNameArg)
|
|
22867
|
+
return;
|
|
22923
22868
|
if (cd.arguments.positional.length === 1) {
|
|
22924
|
-
if ("block" in cd.arguments)
|
|
22869
|
+
if ("block" in cd.arguments)
|
|
22870
|
+
methodArg = cd.arguments.block;
|
|
22925
22871
|
else {
|
|
22926
22872
|
op.a.warnUnsupported(cd.callNode, "Kernel#define_singleton_method called with wrong number of arguments");
|
|
22927
22873
|
return;
|
|
@@ -22931,109 +22877,104 @@ var kernel_default = {
|
|
|
22931
22877
|
op.a.warnUnsupported(cd.callNode, "Kernel#define_singleton_method called with non-object method argument");
|
|
22932
22878
|
return;
|
|
22933
22879
|
}
|
|
22934
|
-
const mVar = op.cvp.methodsVar(
|
|
22935
|
-
|
|
22936
|
-
|
|
22937
|
-
|
|
22938
|
-
|
|
22939
|
-
|
|
22940
|
-
|
|
22941
|
-
|
|
22942
|
-
|
|
22943
|
-
|
|
22944
|
-
|
|
22945
|
-
|
|
22946
|
-
|
|
22947
|
-
|
|
22948
|
-
|
|
22949
|
-
(
|
|
22950
|
-
|
|
22951
|
-
|
|
22952
|
-
|
|
22953
|
-
|
|
22954
|
-
|
|
22955
|
-
|
|
22956
|
-
|
|
22957
|
-
|
|
22958
|
-
|
|
22959
|
-
|
|
22960
|
-
|
|
22961
|
-
(ft) => {
|
|
22962
|
-
if (ft instanceof FunctionToken) {
|
|
22963
|
-
assert5(ft.kind !== "method");
|
|
22964
|
-
op.solver.addTokenConstraint(ft.toKind("method", op), mVar);
|
|
22965
|
-
} else if (ft instanceof NativeFunctionToken) op.solver.addTokenConstraint(ft, mVar);
|
|
22966
|
-
else ft;
|
|
22967
|
-
}
|
|
22968
|
-
);
|
|
22969
|
-
else op.a.warnUnsupported(cd.callNode, "Kernel#define_singleton_method got non-Proc/Method token");
|
|
22970
|
-
} else {
|
|
22971
|
-
mt;
|
|
22972
|
-
op.a.warnUnsupported(cd.callNode, "Kernel#define_singleton_method got non-object method token");
|
|
22973
|
-
}
|
|
22880
|
+
const mVar = op.cvp.methodsVar(op.singletonClass(base), lNameArg.type === "symbol" ? lNameArg.value.slice(1) : lNameArg.value);
|
|
22881
|
+
op.addForAllTokensConstraint(methodArg, TokenListener.NATIVE_KERNEL_DEFINE_SINGLETON_METHOD, { t: base, s: mVar.name }, (mt) => {
|
|
22882
|
+
if (mt instanceof ObjectToken) {
|
|
22883
|
+
if (mt instanceof MethodToken)
|
|
22884
|
+
op.solver.addForAllTokensConstraint(op.cvp.ancestorsVar(op.singletonClass(mt.receiver)), TokenListener.NATIVE_KERNEL_DEFINE_SINGLETON_METHOD_METHOD, { t: base, s: mVar.name }, (t15) => {
|
|
22885
|
+
if (t15 instanceof ObjectToken) {
|
|
22886
|
+
if (!t15.isClassLikeToken())
|
|
22887
|
+
assert5.fail(`Expected class or module token, got ${t15}`);
|
|
22888
|
+
op.solver.addSubsetConstraint(op.cvp.methodsVar(t15, mt.methodName), mVar);
|
|
22889
|
+
} else
|
|
22890
|
+
t15;
|
|
22891
|
+
});
|
|
22892
|
+
else if (mt.klass === op.state.globalNatives.Proc)
|
|
22893
|
+
op.solver.addForAllTokensConstraint(op.cvp.methodsVar(op.singletonClass(mt), "call"), TokenListener.NATIVE_KERNEL_DEFINE_SINGLETON_METHOD_PROC, { t: base, s: mVar.name }, (ft) => {
|
|
22894
|
+
if (ft instanceof FunctionToken) {
|
|
22895
|
+
assert5(ft.kind !== "method");
|
|
22896
|
+
op.solver.addTokenConstraint(ft.toKind("method", op), mVar);
|
|
22897
|
+
} else if (ft instanceof NativeFunctionToken)
|
|
22898
|
+
op.solver.addTokenConstraint(ft, mVar);
|
|
22899
|
+
else
|
|
22900
|
+
ft;
|
|
22901
|
+
});
|
|
22902
|
+
else
|
|
22903
|
+
op.a.warnUnsupported(cd.callNode, "Kernel#define_singleton_method got non-Proc/Method token");
|
|
22904
|
+
} else {
|
|
22905
|
+
mt;
|
|
22906
|
+
op.a.warnUnsupported(cd.callNode, "Kernel#define_singleton_method got non-object method token");
|
|
22974
22907
|
}
|
|
22975
|
-
);
|
|
22908
|
+
});
|
|
22976
22909
|
},
|
|
22977
22910
|
method({ base, op, cd }) {
|
|
22978
22911
|
const lNameArg = literalArg(op, cd, cd.arguments?.positional?.[0], "Kernel#method");
|
|
22979
|
-
if (!lNameArg)
|
|
22912
|
+
if (!lNameArg)
|
|
22913
|
+
return;
|
|
22980
22914
|
const name = lNameArg.type === "symbol" ? lNameArg.value.slice(1) : lNameArg.value;
|
|
22981
|
-
op.solver.addTokenConstraint(
|
|
22982
|
-
op.tokenFactory.createMethodToken(op.state.globalNatives.Method, base, name),
|
|
22983
|
-
cd.result
|
|
22984
|
-
);
|
|
22915
|
+
op.solver.addTokenConstraint(op.tokenFactory.createMethodToken(op.state.globalNatives.Method, base, name), cd.result);
|
|
22985
22916
|
},
|
|
22986
22917
|
instance_variable_get({ base, op, cd }) {
|
|
22987
22918
|
const lNameArg = literalArg(op, cd, cd.arguments?.positional?.[0], "Kernel#instance_variable_get");
|
|
22988
|
-
if (!lNameArg)
|
|
22919
|
+
if (!lNameArg)
|
|
22920
|
+
return;
|
|
22989
22921
|
const name = lNameArg.type === "symbol" ? lNameArg.value.slice(1) : lNameArg.value;
|
|
22990
|
-
if (name.startsWith("@"))
|
|
22991
|
-
|
|
22922
|
+
if (name.startsWith("@"))
|
|
22923
|
+
op.solver.addSubsetConstraint(op.cvp.objPropVar(base, name), cd.result);
|
|
22924
|
+
else
|
|
22925
|
+
op.a.warnUnsupported(cd.callNode, "Kernel#instance_variable_get called with invalid ivar name");
|
|
22992
22926
|
},
|
|
22993
22927
|
instance_variable_set({ base, op, cd }) {
|
|
22994
22928
|
const valueArg = cd.arguments?.positional?.[1];
|
|
22995
|
-
if (!(valueArg instanceof ConstraintVar || valueArg instanceof TokenInterface))
|
|
22996
|
-
|
|
22929
|
+
if (!(valueArg instanceof ConstraintVar || valueArg instanceof TokenInterface))
|
|
22930
|
+
return;
|
|
22931
|
+
if (cd.result)
|
|
22932
|
+
op.inclusionConstraint(valueArg, cd.result);
|
|
22997
22933
|
const lNameArg = literalArg(op, cd, cd.arguments?.positional?.[0], "Kernel#instance_variable_set");
|
|
22998
|
-
if (!lNameArg)
|
|
22934
|
+
if (!lNameArg)
|
|
22935
|
+
return;
|
|
22999
22936
|
const name = lNameArg.type === "symbol" ? lNameArg.value.slice(1) : lNameArg.value;
|
|
23000
|
-
if (name.startsWith("@"))
|
|
23001
|
-
|
|
22937
|
+
if (name.startsWith("@"))
|
|
22938
|
+
op.inclusionConstraint(valueArg, op.cvp.objPropVar(base, name));
|
|
22939
|
+
else
|
|
22940
|
+
op.a.warnUnsupported(cd.callNode, "Kernel#instance_variable_set called with invalid ivar name");
|
|
23002
22941
|
}
|
|
23003
22942
|
},
|
|
23004
|
-
// TODO: Remove this?
|
|
23005
22943
|
staticMethods: globalKernelMethods
|
|
23006
22944
|
};
|
|
23007
22945
|
|
|
23008
|
-
// ../ruby-analyzer/
|
|
22946
|
+
// ../ruby-analyzer/dist/natives/models/object.js
|
|
23009
22947
|
var object_default = {
|
|
23010
22948
|
superclass: "BasicObject",
|
|
23011
22949
|
includes: ["Kernel"],
|
|
23012
22950
|
methods: {
|
|
23013
|
-
// TODO: This is actually defined on Kernel
|
|
23014
22951
|
extend: ({ base, op, cd }) => {
|
|
23015
|
-
if (cd.arguments?.pSplat)
|
|
22952
|
+
if (cd.arguments?.pSplat)
|
|
22953
|
+
op.a.warnUnsupported(cd.callNode, "Object#extend called with splat arguments");
|
|
23016
22954
|
const av = op.cvp.ancestorsVar(op.singletonClass(base));
|
|
23017
22955
|
for (const arg of cd.arguments?.positional ?? [])
|
|
23018
22956
|
if (arg instanceof ConstraintVar || arg instanceof ObjectToken)
|
|
23019
|
-
op.addForAllTokensConstraint(arg,
|
|
22957
|
+
op.addForAllTokensConstraint(arg, TokenListener.NATIVE_OBJECT_EXTEND, { t: base }, (t15) => {
|
|
23020
22958
|
if (t15 instanceof ObjectToken) {
|
|
23021
22959
|
if (t15.klass === op.state.globalNatives.Module)
|
|
23022
22960
|
op.solver.addSubsetConstraint(op.cvp.ancestorsVar(t15), av);
|
|
23023
|
-
} else
|
|
22961
|
+
} else
|
|
22962
|
+
t15;
|
|
23024
22963
|
});
|
|
23025
|
-
else
|
|
22964
|
+
else
|
|
22965
|
+
arg;
|
|
23026
22966
|
}
|
|
23027
22967
|
}
|
|
23028
22968
|
};
|
|
23029
22969
|
|
|
23030
|
-
// ../ruby-analyzer/
|
|
22970
|
+
// ../ruby-analyzer/dist/natives/models/singleton.js
|
|
23031
22971
|
var singleton_default = {
|
|
23032
22972
|
Singleton: {
|
|
23033
22973
|
staticMethods: {
|
|
23034
22974
|
included({ op, cd }) {
|
|
23035
22975
|
const klass = cd.arguments?.positional?.[0];
|
|
23036
|
-
if (!(klass instanceof ConstraintVar || klass instanceof TokenInterface))
|
|
22976
|
+
if (!(klass instanceof ConstraintVar || klass instanceof TokenInterface))
|
|
22977
|
+
return;
|
|
23037
22978
|
op.callMethod(klass, "extend", {
|
|
23038
22979
|
...cd,
|
|
23039
22980
|
arguments: {
|
|
@@ -23054,7 +22995,7 @@ var singleton_default = {
|
|
|
23054
22995
|
}
|
|
23055
22996
|
};
|
|
23056
22997
|
|
|
23057
|
-
// ../ruby-analyzer/
|
|
22998
|
+
// ../ruby-analyzer/dist/natives/ruby-model.js
|
|
23058
22999
|
var rubyModel = {
|
|
23059
23000
|
name: "Ruby",
|
|
23060
23001
|
modules: {
|
|
@@ -23081,7 +23022,8 @@ var rubyModel = {
|
|
|
23081
23022
|
}))(p);
|
|
23082
23023
|
if (it) {
|
|
23083
23024
|
op.solver.addTokenConstraint(it, cd.result);
|
|
23084
|
-
if (!isNative)
|
|
23025
|
+
if (!isNative)
|
|
23026
|
+
op.state.classInstantiations.push([base.allocSite, cd.callNode, cd.caller]);
|
|
23085
23027
|
op.callMethod(it, "initialize", {
|
|
23086
23028
|
...cd,
|
|
23087
23029
|
result: void 0
|
|
@@ -23094,32 +23036,25 @@ var rubyModel = {
|
|
|
23094
23036
|
Module: module_default,
|
|
23095
23037
|
Object: object_default,
|
|
23096
23038
|
BasicObject: basic_object_default,
|
|
23097
|
-
// Proc objects are modelled by sticking a FunctionToken into the "call" method
|
|
23098
|
-
// of the Proc instance's singleton class.
|
|
23099
23039
|
Proc: {
|
|
23100
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
23101
23040
|
newInstance: () => {
|
|
23102
23041
|
},
|
|
23103
23042
|
staticMethods: {
|
|
23104
23043
|
new: ({ op, cd }) => {
|
|
23105
|
-
if (cd.result)
|
|
23044
|
+
if (cd.result)
|
|
23045
|
+
op.inclusionConstraint(cd.arguments?.block, cd.result);
|
|
23106
23046
|
}
|
|
23107
23047
|
}
|
|
23108
23048
|
},
|
|
23109
|
-
// We cannot model Method objects as neatly as Proc objects, as we need to pass on the bound
|
|
23110
|
-
// receiver of the Method instead of the Method object itself when the Method is called.
|
|
23111
|
-
// Method objects are modelled by the creation of a MethodToken in Kernel#method.
|
|
23112
23049
|
Method: {
|
|
23113
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
23114
23050
|
newInstance() {
|
|
23115
23051
|
}
|
|
23116
|
-
// TODO: Add a "call" method that passes on the call to the underlying method with the bound receiver
|
|
23117
23052
|
},
|
|
23118
23053
|
...nokogiri_default
|
|
23119
23054
|
}
|
|
23120
23055
|
};
|
|
23121
23056
|
|
|
23122
|
-
// ../ruby-analyzer/
|
|
23057
|
+
// ../ruby-analyzer/dist/natives/native-builder.js
|
|
23123
23058
|
function makeNative(name) {
|
|
23124
23059
|
return `%${name}`;
|
|
23125
23060
|
}
|
|
@@ -23135,7 +23070,8 @@ function buildNatives(solver, tokenFactory, cvp) {
|
|
|
23135
23070
|
if (name === "Class") {
|
|
23136
23071
|
ct = rubyClassToken;
|
|
23137
23072
|
assert6.strictEqual(tokenFactory.canonicalizeToken(ct), ct);
|
|
23138
|
-
} else if (objKlass === "Class")
|
|
23073
|
+
} else if (objKlass === "Class")
|
|
23074
|
+
ct = tokenFactory.createClassToken(n12);
|
|
23139
23075
|
else {
|
|
23140
23076
|
objKlass;
|
|
23141
23077
|
ct = tokenFactory.createInstanceToken(assertDefined(created.Module), n12);
|
|
@@ -23145,18 +23081,12 @@ function buildNatives(solver, tokenFactory, cvp) {
|
|
|
23145
23081
|
for (const v of [cvp.ancestorsVar(ct), cvp.constantVar(makeConstant(`::${name}`))])
|
|
23146
23082
|
solver.addTokenConstraint(ct, v);
|
|
23147
23083
|
for (const [mname, invoke] of "methods" in klass ? Object.entries(klass.methods) : []) {
|
|
23148
|
-
solver.addTokenConstraint(
|
|
23149
|
-
tokenFactory.createNativeFunctionToken(makeNative(`${name}#${mname}`), invoke),
|
|
23150
|
-
cvp.methodsVar(ct, mname)
|
|
23151
|
-
);
|
|
23084
|
+
solver.addTokenConstraint(tokenFactory.createNativeFunctionToken(makeNative(`${name}#${mname}`), invoke), cvp.methodsVar(ct, mname));
|
|
23152
23085
|
}
|
|
23153
23086
|
if ("staticMethods" in klass) {
|
|
23154
23087
|
const sct = tokenFactory.createSingletonClassToken(ct);
|
|
23155
23088
|
for (const [mname, invoke] of Object.entries(klass.staticMethods))
|
|
23156
|
-
solver.addTokenConstraint(
|
|
23157
|
-
tokenFactory.createNativeFunctionToken(makeNative(`${name}$${mname}`), invoke),
|
|
23158
|
-
cvp.methodsVar(sct, mname)
|
|
23159
|
-
);
|
|
23089
|
+
solver.addTokenConstraint(tokenFactory.createNativeFunctionToken(makeNative(`${name}$${mname}`), invoke), cvp.methodsVar(sct, mname));
|
|
23160
23090
|
}
|
|
23161
23091
|
}
|
|
23162
23092
|
const finished = created;
|
|
@@ -23165,10 +23095,7 @@ function buildNatives(solver, tokenFactory, cvp) {
|
|
|
23165
23095
|
const ct = finished[name];
|
|
23166
23096
|
const superCt = finished["superclass" in klass ? klass.superclass : "Object"];
|
|
23167
23097
|
solver.addSubsetConstraint(cvp.ancestorsVar(superCt), cvp.ancestorsVar(ct));
|
|
23168
|
-
solver.addSubsetConstraint(
|
|
23169
|
-
cvp.ancestorsVar(tokenFactory.createSingletonClassToken(superCt)),
|
|
23170
|
-
cvp.ancestorsVar(tokenFactory.createSingletonClassToken(ct))
|
|
23171
|
-
);
|
|
23098
|
+
solver.addSubsetConstraint(cvp.ancestorsVar(tokenFactory.createSingletonClassToken(superCt)), cvp.ancestorsVar(tokenFactory.createSingletonClassToken(ct)));
|
|
23172
23099
|
}
|
|
23173
23100
|
const op = { solver, tokenFactory, cvp };
|
|
23174
23101
|
for (const [name, klass] of [...t5(rubyModel.modules), ...t5(rubyModel.classes)]) {
|
|
@@ -23180,17 +23107,22 @@ function buildNatives(solver, tokenFactory, cvp) {
|
|
|
23180
23107
|
solver.addSubsetConstraint(cvp.ancestorsVar(incCt), av);
|
|
23181
23108
|
}
|
|
23182
23109
|
}
|
|
23183
|
-
if ("setup" in klass)
|
|
23110
|
+
if ("setup" in klass)
|
|
23111
|
+
klass.setup(finished[name], op);
|
|
23184
23112
|
}
|
|
23185
23113
|
return finished;
|
|
23186
23114
|
}
|
|
23187
23115
|
|
|
23188
|
-
// ../ruby-analyzer/
|
|
23116
|
+
// ../ruby-analyzer/dist/operations.js
|
|
23189
23117
|
import assert7 from "node:assert";
|
|
23190
23118
|
import fs2 from "node:fs";
|
|
23191
23119
|
import { basename, dirname as dirname2, relative } from "node:path";
|
|
23192
23120
|
var gemDirRegex = /^(?<name>[\w-_]+)-(?<version>\d+[^-]*)/;
|
|
23193
23121
|
var Operations = class {
|
|
23122
|
+
solver;
|
|
23123
|
+
state;
|
|
23124
|
+
constraintVarProducer;
|
|
23125
|
+
tokenFactory;
|
|
23194
23126
|
constructor(solver, state, constraintVarProducer, tokenFactory) {
|
|
23195
23127
|
this.solver = solver;
|
|
23196
23128
|
this.state = state;
|
|
@@ -23217,52 +23149,39 @@ var Operations = class {
|
|
|
23217
23149
|
const { solver, cvp } = this;
|
|
23218
23150
|
const onAncestorToken = (baseToken, klass) => {
|
|
23219
23151
|
if (logger.isDebugEnabled())
|
|
23220
|
-
logger.debug(
|
|
23221
|
-
|
|
23222
|
-
);
|
|
23223
|
-
solver.addForAllTokensConstraint(
|
|
23224
|
-
cvp.methodsVar(klass, methodName),
|
|
23225
|
-
0 /* Call */,
|
|
23226
|
-
{ n: cd.callNode, s: methodName, t: baseToken },
|
|
23227
|
-
(t15) => handleCall.call(this, cd, baseToken, t15)
|
|
23228
|
-
);
|
|
23152
|
+
logger.debug(`Processing call to method '${methodName}' on ancestor ${klass} of base token ${baseToken} at ${nodeLocationToString(cd.callNode)}`);
|
|
23153
|
+
solver.addForAllTokensConstraint(cvp.methodsVar(klass, methodName), TokenListener.Call, { n: cd.callNode, s: methodName, t: baseToken }, (t15) => handleCall.call(this, cd, baseToken, t15));
|
|
23229
23154
|
};
|
|
23230
23155
|
const onBaseToken = (baseToken) => {
|
|
23231
23156
|
if (logger.isDebugEnabled())
|
|
23232
|
-
logger.debug(
|
|
23233
|
-
|
|
23234
|
-
)
|
|
23235
|
-
|
|
23236
|
-
|
|
23237
|
-
|
|
23238
|
-
|
|
23239
|
-
|
|
23240
|
-
|
|
23241
|
-
if (!t15.isClassLikeToken()) assert7.fail(`Expected class or module token, got ${t15}`);
|
|
23242
|
-
onAncestorToken(baseToken, t15);
|
|
23243
|
-
} else {
|
|
23244
|
-
t15;
|
|
23245
|
-
logger.error(`Unexpected token type in call ancestors: ${t15} at ${nodeLocationToString(cd.callNode)}`);
|
|
23246
|
-
}
|
|
23157
|
+
logger.debug(`Processing call to method '${methodName}' on base token ${baseToken} at ${nodeLocationToString(cd.callNode)}`);
|
|
23158
|
+
solver.addForAllTokensConstraint(cvp.ancestorsVar(this.singletonClass(baseToken)), TokenListener.CALL_ANCESTORS, { n: cd.callNode, s: methodName, t: baseToken }, (t15) => {
|
|
23159
|
+
if (t15 instanceof ObjectToken) {
|
|
23160
|
+
if (!t15.isClassLikeToken())
|
|
23161
|
+
assert7.fail(`Expected class or module token, got ${t15}`);
|
|
23162
|
+
onAncestorToken(baseToken, t15);
|
|
23163
|
+
} else {
|
|
23164
|
+
t15;
|
|
23165
|
+
logger.error(`Unexpected token type in call ancestors: ${t15} at ${nodeLocationToString(cd.callNode)}`);
|
|
23247
23166
|
}
|
|
23248
|
-
);
|
|
23167
|
+
});
|
|
23249
23168
|
};
|
|
23250
23169
|
if (receiver instanceof ConstraintVar)
|
|
23251
|
-
solver.addForAllTokensConstraint(
|
|
23252
|
-
|
|
23253
|
-
|
|
23254
|
-
|
|
23255
|
-
|
|
23256
|
-
|
|
23257
|
-
|
|
23258
|
-
|
|
23259
|
-
);
|
|
23260
|
-
else onBaseToken(receiver);
|
|
23170
|
+
solver.addForAllTokensConstraint(receiver, TokenListener.CALL_BASE, { n: cd.callNode, s: methodName }, (baseToken) => {
|
|
23171
|
+
if (baseToken instanceof ObjectToken)
|
|
23172
|
+
onBaseToken(baseToken);
|
|
23173
|
+
else
|
|
23174
|
+
baseToken;
|
|
23175
|
+
});
|
|
23176
|
+
else
|
|
23177
|
+
onBaseToken(receiver);
|
|
23261
23178
|
function handleCall(cd2, base, t15) {
|
|
23262
23179
|
if (logger.isVerboseEnabled())
|
|
23263
23180
|
logger.verbose(`Call to ${base}.${methodName} at ${nodeLocationToString(cd2.callNode)} resolved to ${t15}`);
|
|
23264
|
-
if (t15 instanceof FunctionToken)
|
|
23265
|
-
|
|
23181
|
+
if (t15 instanceof FunctionToken)
|
|
23182
|
+
this.dispatchCall(t15, base, cd2);
|
|
23183
|
+
else if (t15 instanceof NativeFunctionToken)
|
|
23184
|
+
t15.invoke({ base, op: this, cd: cd2 });
|
|
23266
23185
|
else {
|
|
23267
23186
|
t15;
|
|
23268
23187
|
logger.error(`Unexpected token type in call: ${t15} at ${nodeLocationToString(cd2.callNode)}`);
|
|
@@ -23271,12 +23190,7 @@ var Operations = class {
|
|
|
23271
23190
|
}
|
|
23272
23191
|
dispatchCall(t15, base, cd) {
|
|
23273
23192
|
const { cvp, solver, a } = this;
|
|
23274
|
-
solver.callGraph.addEdge(
|
|
23275
|
-
cd.callNode,
|
|
23276
|
-
cd.caller,
|
|
23277
|
-
assertDefined(a.functionInfos.get(t15.fun))
|
|
23278
|
-
// kind
|
|
23279
|
-
);
|
|
23193
|
+
solver.callGraph.addEdge(cd.callNode, cd.caller, assertDefined(a.functionInfos.get(t15.fun)));
|
|
23280
23194
|
const args = cd.arguments;
|
|
23281
23195
|
if (args) {
|
|
23282
23196
|
const params = t15.parameters?.namedChildren ?? [];
|
|
@@ -23284,9 +23198,11 @@ var Operations = class {
|
|
|
23284
23198
|
if ((arg instanceof ConstraintVar || arg instanceof TokenInterface) && params[i])
|
|
23285
23199
|
this.inclusionConstraint(arg, cvp.nodeVar(params[i]));
|
|
23286
23200
|
}
|
|
23287
|
-
if (args.block)
|
|
23201
|
+
if (args.block)
|
|
23202
|
+
this.inclusionConstraint(args.block, cvp.blockParamVar(t15.fun));
|
|
23288
23203
|
}
|
|
23289
|
-
if (t15.kind === "method")
|
|
23204
|
+
if (t15.kind === "method")
|
|
23205
|
+
solver.addTokenConstraint(base, cvp.selfVar(t15.fun));
|
|
23290
23206
|
else {
|
|
23291
23207
|
t15.kind;
|
|
23292
23208
|
solver.addSubsetConstraint(cvp.selfVar(t15.scope), cvp.selfVar(t15.fun));
|
|
@@ -23295,14 +23211,20 @@ var Operations = class {
|
|
|
23295
23211
|
solver.addSubsetConstraint(cvp.returnVar(t15.fun), cd.result);
|
|
23296
23212
|
}
|
|
23297
23213
|
inclusionConstraint(from, to) {
|
|
23298
|
-
if (from === void 0)
|
|
23299
|
-
|
|
23300
|
-
|
|
23214
|
+
if (from === void 0)
|
|
23215
|
+
return;
|
|
23216
|
+
if (from instanceof ConstraintVar)
|
|
23217
|
+
this.solver.addSubsetConstraint(from, to);
|
|
23218
|
+
else
|
|
23219
|
+
this.solver.addTokenConstraint(from, to);
|
|
23301
23220
|
}
|
|
23302
23221
|
addForAllTokensConstraint(v, key, opts, listener) {
|
|
23303
|
-
if (v === void 0)
|
|
23304
|
-
|
|
23305
|
-
|
|
23222
|
+
if (v === void 0)
|
|
23223
|
+
return;
|
|
23224
|
+
if (v instanceof ConstraintVar)
|
|
23225
|
+
this.solver.addForAllTokensConstraint(v, key, opts, listener);
|
|
23226
|
+
else
|
|
23227
|
+
listener(v);
|
|
23306
23228
|
}
|
|
23307
23229
|
evalArg(arg, fallback) {
|
|
23308
23230
|
if (isStringNode(arg)) {
|
|
@@ -23314,57 +23236,51 @@ var Operations = class {
|
|
|
23314
23236
|
return { type: "symbol", value: s };
|
|
23315
23237
|
} else if (isBareSymbolNode(arg) || isDelimitedSymbolNode(arg))
|
|
23316
23238
|
this.a.warnUnsupported(arg, `${arg.type} arguments in calls`);
|
|
23317
|
-
else if (isMethodNode(arg) || isSingletonMethodNode(arg))
|
|
23318
|
-
|
|
23319
|
-
|
|
23320
|
-
|
|
23321
|
-
|
|
23322
|
-
|
|
23323
|
-
|
|
23324
|
-
|
|
23325
|
-
|
|
23326
|
-
|
|
23327
|
-
|
|
23328
|
-
|
|
23329
|
-
|
|
23330
|
-
|
|
23331
|
-
|
|
23332
|
-
|
|
23333
|
-
|
|
23334
|
-
|
|
23335
|
-
|
|
23336
|
-
|
|
23337
|
-
|
|
23338
|
-
}
|
|
23339
|
-
const parent = dirname2(dirPath);
|
|
23340
|
-
if (parent === dirPath || dirPath === this.a.rootDir)
|
|
23341
|
-
return new PackageInfo(
|
|
23342
|
-
"<main>",
|
|
23343
|
-
void 0,
|
|
23344
|
-
parent === dirPath ? "" : relative(this.a.rootDir, dirPath),
|
|
23345
|
-
isEntry
|
|
23346
|
-
);
|
|
23347
|
-
return this.getContainingGem(parent, isEntry);
|
|
23239
|
+
else if (isMethodNode(arg) || isSingletonMethodNode(arg))
|
|
23240
|
+
return { type: "symbol", value: `:${arg.nameNode.text}` };
|
|
23241
|
+
else
|
|
23242
|
+
return fallback?.();
|
|
23243
|
+
}
|
|
23244
|
+
getContainingGem = cache((dirPath, isEntry) => {
|
|
23245
|
+
const dirName = basename(dirPath);
|
|
23246
|
+
const entries = fs2.readdirSync(dirPath, { withFileTypes: true });
|
|
23247
|
+
const entry = entries.find((entry2) => entry2.isFile() && (entry2.name === "Rakefile" || entry2.name.endsWith(".gemspec")) || entry2.isDirectory() && entry2.name === "lib");
|
|
23248
|
+
if (entry) {
|
|
23249
|
+
let name;
|
|
23250
|
+
let version;
|
|
23251
|
+
const match2 = gemDirRegex.exec(dirName);
|
|
23252
|
+
if (match2)
|
|
23253
|
+
({ name, version } = match2.groups);
|
|
23254
|
+
else {
|
|
23255
|
+
const e5 = entry.name.endsWith(".gemspec") ? entry : entries.find((e6) => e6.name.endsWith(".gemspec"));
|
|
23256
|
+
name = e5?.name.replace(/\.gemspec$/, "");
|
|
23257
|
+
}
|
|
23258
|
+
if (name !== void 0)
|
|
23259
|
+
return new PackageInfo(name, version, relative(this.a.rootDir, dirPath), isEntry);
|
|
23348
23260
|
}
|
|
23349
|
-
|
|
23261
|
+
const parent = dirname2(dirPath);
|
|
23262
|
+
if (parent === dirPath || dirPath === this.a.rootDir)
|
|
23263
|
+
return new PackageInfo("<main>", void 0, parent === dirPath ? "" : relative(this.a.rootDir, dirPath), isEntry);
|
|
23264
|
+
return this.getContainingGem(parent, isEntry);
|
|
23265
|
+
});
|
|
23350
23266
|
};
|
|
23351
23267
|
|
|
23352
|
-
// ../ruby-analyzer/
|
|
23268
|
+
// ../ruby-analyzer/dist/parser.js
|
|
23353
23269
|
import Parser from "tree-sitter";
|
|
23354
23270
|
import Ruby from "tree-sitter-ruby";
|
|
23355
23271
|
var parser = new Parser();
|
|
23356
23272
|
parser.setLanguage(Ruby);
|
|
23357
23273
|
|
|
23358
|
-
// ../ruby-analyzer/
|
|
23274
|
+
// ../ruby-analyzer/dist/ruby-ast-visitor.js
|
|
23359
23275
|
import assert8 from "node:assert";
|
|
23360
23276
|
|
|
23361
|
-
// ../ruby-analyzer/
|
|
23277
|
+
// ../ruby-analyzer/dist/ruby-vulnerabilities.js
|
|
23362
23278
|
var reFQN = /^(?:(?:<<\w*|\w+)(?:::(?:<<\w*|\w+))*)?#(?:(?:\w+|\?)\.)?[^\t\n .]+$/;
|
|
23363
23279
|
function validateVulnerabilityID(id) {
|
|
23364
23280
|
return reFQN.test(id);
|
|
23365
23281
|
}
|
|
23366
23282
|
|
|
23367
|
-
// ../ruby-analyzer/
|
|
23283
|
+
// ../ruby-analyzer/dist/types/ruby-ast-helper-types.js
|
|
23368
23284
|
var functionTypes = ["method", "singleton_method", "block", "do_block"];
|
|
23369
23285
|
var functionTypeSet = new Set(functionTypes);
|
|
23370
23286
|
function isFunctionNode(node) {
|
|
@@ -23373,20 +23289,23 @@ function isFunctionNode(node) {
|
|
|
23373
23289
|
var scopeTypes = [...functionTypes, "class", "singleton_class", "module", "program"];
|
|
23374
23290
|
var scopeTypeSet = new Set(scopeTypes);
|
|
23375
23291
|
|
|
23376
|
-
// ../ruby-analyzer/
|
|
23292
|
+
// ../ruby-analyzer/dist/ruby-ast-visitor.js
|
|
23377
23293
|
function isFullyQualifiedConstant(s) {
|
|
23378
23294
|
return s.startsWith("::");
|
|
23379
23295
|
}
|
|
23380
23296
|
var RubyAstVisitor = class {
|
|
23297
|
+
op;
|
|
23298
|
+
moduleInfo;
|
|
23299
|
+
bindings;
|
|
23300
|
+
done = false;
|
|
23301
|
+
constantNesting = [];
|
|
23302
|
+
scopes = [];
|
|
23303
|
+
handledConstants = new NodeSet();
|
|
23381
23304
|
constructor(op, moduleInfo, bindings) {
|
|
23382
23305
|
this.op = op;
|
|
23383
23306
|
this.moduleInfo = moduleInfo;
|
|
23384
23307
|
this.bindings = bindings;
|
|
23385
23308
|
}
|
|
23386
|
-
done = false;
|
|
23387
|
-
constantNesting = [];
|
|
23388
|
-
scopes = [];
|
|
23389
|
-
handledConstants = new NodeSet();
|
|
23390
23309
|
getSurroundingScope() {
|
|
23391
23310
|
return assertDefined(this.scopes.at(-1));
|
|
23392
23311
|
}
|
|
@@ -23398,20 +23317,17 @@ var RubyAstVisitor = class {
|
|
|
23398
23317
|
const i = nesting.findLastIndex((c) => c.startsWith("::"));
|
|
23399
23318
|
return i === -1 ? makeConstant(`::${nesting.join("::")}`) : makeConstant(nesting.slice(i).join("::"));
|
|
23400
23319
|
}
|
|
23401
|
-
/* Helper to set up constraints for constants and scope resolution nodes. */
|
|
23402
23320
|
expVar(n12) {
|
|
23403
23321
|
assert8(!this.done, "expVar called after visitor is done");
|
|
23404
|
-
const {
|
|
23405
|
-
|
|
23406
|
-
|
|
23407
|
-
handledConstants
|
|
23408
|
-
} = this;
|
|
23409
|
-
if (isIdentifierNode(n12)) return cvp.identVar(n12, this.bindings);
|
|
23322
|
+
const { op: { solver, cvp }, constantNesting, handledConstants } = this;
|
|
23323
|
+
if (isIdentifierNode(n12))
|
|
23324
|
+
return cvp.identVar(n12, this.bindings);
|
|
23410
23325
|
else if (isScopeResolutionNode(n12) || isConstantNode(n12)) {
|
|
23411
23326
|
const nvar = cvp.nodeVar(n12);
|
|
23412
23327
|
if (!handledConstants.has(n12)) {
|
|
23413
23328
|
const c = n12.text;
|
|
23414
|
-
if (isFullyQualifiedConstant(c))
|
|
23329
|
+
if (isFullyQualifiedConstant(c))
|
|
23330
|
+
solver.addSubsetConstraint(cvp.constantVar(makeConstant(c)), nvar);
|
|
23415
23331
|
else {
|
|
23416
23332
|
for (let i = 0; i <= constantNesting.length; i++) {
|
|
23417
23333
|
const fq = this.fqConstant([...constantNesting.slice(0, i), c]);
|
|
@@ -23421,42 +23337,31 @@ var RubyAstVisitor = class {
|
|
|
23421
23337
|
const classOrModule = assertDefined(this.scopes.findLast((s) => isClassNode(s) || isModuleNode(s)));
|
|
23422
23338
|
assert8.strictEqual(classOrModule.nameNode.text, constantNesting.at(-1));
|
|
23423
23339
|
const ct = this.classOrModuleToken(this.fqConstant(), classOrModule);
|
|
23424
|
-
solver.addForAllTokensConstraint(
|
|
23425
|
-
|
|
23426
|
-
|
|
23427
|
-
|
|
23428
|
-
|
|
23429
|
-
|
|
23430
|
-
|
|
23431
|
-
|
|
23432
|
-
|
|
23433
|
-
} else t15;
|
|
23434
|
-
}
|
|
23435
|
-
);
|
|
23340
|
+
solver.addForAllTokensConstraint(cvp.ancestorsVar(ct), TokenListener.CONSTANTS_ANCESTORS, { n: n12 }, (t15) => {
|
|
23341
|
+
if (t15 instanceof ObjectToken) {
|
|
23342
|
+
if (!t15.isClassOrModuleToken())
|
|
23343
|
+
assert8.fail(`Expected class or module token, got ${t15}`);
|
|
23344
|
+
const fq = makeConstant(`${t15.allocSite}::${c}`);
|
|
23345
|
+
solver.addSubsetConstraint(cvp.constantVar(fq), nvar);
|
|
23346
|
+
} else
|
|
23347
|
+
t15;
|
|
23348
|
+
});
|
|
23436
23349
|
}
|
|
23437
23350
|
}
|
|
23438
23351
|
handledConstants.add(n12);
|
|
23439
23352
|
}
|
|
23440
23353
|
return nvar;
|
|
23441
|
-
} else if (isSelfNode(n12))
|
|
23442
|
-
|
|
23443
|
-
else if (
|
|
23354
|
+
} else if (isSelfNode(n12))
|
|
23355
|
+
return cvp.selfVar(this.getSurroundingScope());
|
|
23356
|
+
else if (isParenthesizedStatementsNode(n12))
|
|
23357
|
+
return n12.lastNamedChild ? this.expVar(n12.lastNamedChild) : void 0;
|
|
23358
|
+
else if (isIfModifierNode(n12) || isUnlessModifierNode(n12))
|
|
23359
|
+
return this.expVar(n12.bodyNode);
|
|
23444
23360
|
return cvp.nodeVar(n12);
|
|
23445
23361
|
}
|
|
23446
23362
|
*program(node) {
|
|
23447
|
-
const {
|
|
23448
|
-
|
|
23449
|
-
solver,
|
|
23450
|
-
cvp,
|
|
23451
|
-
tokenFactory,
|
|
23452
|
-
state: { globalNatives }
|
|
23453
|
-
},
|
|
23454
|
-
scopes
|
|
23455
|
-
} = this;
|
|
23456
|
-
solver.addTokenConstraint(
|
|
23457
|
-
tokenFactory.createInstanceToken(globalNatives.Object, makeNative("main")),
|
|
23458
|
-
cvp.selfVar(node)
|
|
23459
|
-
);
|
|
23363
|
+
const { op: { solver, cvp, tokenFactory, state: { globalNatives } }, scopes } = this;
|
|
23364
|
+
solver.addTokenConstraint(tokenFactory.createInstanceToken(globalNatives.Object, makeNative("main")), cvp.selfVar(node));
|
|
23460
23365
|
solver.addTokenConstraint(globalNatives.Object, cvp.defaultDefineeVar(node));
|
|
23461
23366
|
scopes.push(node);
|
|
23462
23367
|
yield* node.namedChildren;
|
|
@@ -23490,14 +23395,8 @@ var RubyAstVisitor = class {
|
|
|
23490
23395
|
this.handleCall(node, this.op.cvp.blockParamVar(meth), "call", this.parseArgumentList(node.firstNamedChild));
|
|
23491
23396
|
}
|
|
23492
23397
|
call(node) {
|
|
23493
|
-
const methodName = node.methodNode?.text ??
|
|
23494
|
-
(
|
|
23495
|
-
this.handleCall(
|
|
23496
|
-
node,
|
|
23497
|
-
node.receiverNode ? assertDefined(this.expVar(node.receiverNode)) : this.op.cvp.selfVar(this.getSurroundingScope()),
|
|
23498
|
-
methodName,
|
|
23499
|
-
this.parseArgumentList(node.argumentsNode, this.blockToProc(node))
|
|
23500
|
-
);
|
|
23398
|
+
const methodName = node.methodNode?.text ?? (assert8.strictEqual(node.operatorNode?.text, "."), "call");
|
|
23399
|
+
this.handleCall(node, node.receiverNode ? assertDefined(this.expVar(node.receiverNode)) : this.op.cvp.selfVar(this.getSurroundingScope()), methodName, this.parseArgumentList(node.argumentsNode, this.blockToProc(node)));
|
|
23501
23400
|
}
|
|
23502
23401
|
blockToProc(node) {
|
|
23503
23402
|
const { op } = this;
|
|
@@ -23505,7 +23404,8 @@ var RubyAstVisitor = class {
|
|
|
23505
23404
|
let blockNode;
|
|
23506
23405
|
let kind = "proc";
|
|
23507
23406
|
if (isCallNode(node)) {
|
|
23508
|
-
if (!node.blockNode)
|
|
23407
|
+
if (!node.blockNode)
|
|
23408
|
+
return;
|
|
23509
23409
|
blockNode = node.blockNode;
|
|
23510
23410
|
} else {
|
|
23511
23411
|
node.type;
|
|
@@ -23515,10 +23415,7 @@ var RubyAstVisitor = class {
|
|
|
23515
23415
|
}
|
|
23516
23416
|
const procToken = op.tokenFactory.createInstanceToken(op.state.globalNatives.Proc, node);
|
|
23517
23417
|
const sct = op.tokenFactory.createSingletonClassToken(procToken);
|
|
23518
|
-
op.solver.addTokenConstraint(
|
|
23519
|
-
op.tokenFactory.createFunctionToken(blockNode, kind, this.getSurroundingScope(), parametersNode),
|
|
23520
|
-
op.cvp.methodsVar(sct, "call")
|
|
23521
|
-
);
|
|
23418
|
+
op.solver.addTokenConstraint(op.tokenFactory.createFunctionToken(blockNode, kind, this.getSurroundingScope(), parametersNode), op.cvp.methodsVar(sct, "call"));
|
|
23522
23419
|
return procToken;
|
|
23523
23420
|
}
|
|
23524
23421
|
handleCall(node, receiver, methodName, args) {
|
|
@@ -23544,31 +23441,33 @@ var RubyAstVisitor = class {
|
|
|
23544
23441
|
this.registerFunctionInfo(name, node);
|
|
23545
23442
|
const scopeDefinee = cvp.defaultDefineeVar(scope);
|
|
23546
23443
|
solver.addSubsetEdge(scopeDefinee, cvp.defaultDefineeVar(node));
|
|
23547
|
-
solver.addForAllTokensConstraint(
|
|
23548
|
-
|
|
23549
|
-
|
|
23550
|
-
|
|
23551
|
-
|
|
23552
|
-
|
|
23553
|
-
|
|
23554
|
-
|
|
23555
|
-
|
|
23556
|
-
|
|
23557
|
-
|
|
23558
|
-
|
|
23559
|
-
|
|
23560
|
-
if (node.type === "singleton_method") yield node.objectNode;
|
|
23444
|
+
solver.addForAllTokensConstraint(node.type === "method" ? scopeDefinee : this.expVar(node.objectNode), TokenListener.Method, { n: node }, (t15) => {
|
|
23445
|
+
if (t15 instanceof ObjectToken) {
|
|
23446
|
+
if (node.type === "singleton_method")
|
|
23447
|
+
t15 = op.singletonClass(t15);
|
|
23448
|
+
if (t15.isClassLikeToken())
|
|
23449
|
+
solver.addTokenConstraint(functionToken, cvp.methodsVar(t15, name));
|
|
23450
|
+
else
|
|
23451
|
+
logger.error(`Unexpected class of default definee: ${t15.klass} for method ${name}`);
|
|
23452
|
+
} else
|
|
23453
|
+
t15;
|
|
23454
|
+
});
|
|
23455
|
+
if (node.type === "singleton_method")
|
|
23456
|
+
yield node.objectNode;
|
|
23561
23457
|
scopes.push(node);
|
|
23562
23458
|
this.addLastNodeToReturnVarConstraint(node);
|
|
23563
|
-
if (node.bodyNode)
|
|
23564
|
-
|
|
23459
|
+
if (node.bodyNode)
|
|
23460
|
+
yield node.bodyNode;
|
|
23461
|
+
if (node.parametersNode)
|
|
23462
|
+
yield node.parametersNode;
|
|
23565
23463
|
scopes.pop();
|
|
23566
23464
|
}
|
|
23567
23465
|
block_parameter(node) {
|
|
23568
23466
|
const { solver, cvp } = this.op;
|
|
23569
23467
|
const scope = this.getSurroundingScope();
|
|
23570
23468
|
assert8(isFunctionNode(scope), "Block parameter not in function scope");
|
|
23571
|
-
if (node.nameNode)
|
|
23469
|
+
if (node.nameNode)
|
|
23470
|
+
solver.addSubsetConstraint(cvp.blockParamVar(scope), cvp.identVar(node.nameNode, this.bindings));
|
|
23572
23471
|
}
|
|
23573
23472
|
lambda(node) {
|
|
23574
23473
|
const { op } = this;
|
|
@@ -23597,7 +23496,8 @@ var RubyAstVisitor = class {
|
|
|
23597
23496
|
*handleAssignment(node, operator) {
|
|
23598
23497
|
const { solver, cvp, a } = this.op;
|
|
23599
23498
|
yield node.rightNode;
|
|
23600
|
-
if (!["=", "&&=", "||="].includes(operator))
|
|
23499
|
+
if (!["=", "&&=", "||="].includes(operator))
|
|
23500
|
+
return;
|
|
23601
23501
|
const nVar = cvp.nodeVar(node);
|
|
23602
23502
|
const eVar = this.expVar(node.rightNode);
|
|
23603
23503
|
const isLogical = operator !== "=";
|
|
@@ -23605,15 +23505,18 @@ var RubyAstVisitor = class {
|
|
|
23605
23505
|
if (isIdentifierNode(node.leftNode)) {
|
|
23606
23506
|
const lVar = cvp.identVar(node.leftNode, this.bindings);
|
|
23607
23507
|
solver.addSubsetConstraint(eVar, lVar);
|
|
23608
|
-
if (isLogical)
|
|
23508
|
+
if (isLogical)
|
|
23509
|
+
solver.addSubsetConstraint(lVar, nVar);
|
|
23609
23510
|
} else if (isInstanceVariableNode(node.leftNode)) {
|
|
23610
23511
|
const selfVar = cvp.selfVar(this.getSurroundingScope());
|
|
23611
|
-
solver.addForAllTokensConstraint(selfVar,
|
|
23512
|
+
solver.addForAllTokensConstraint(selfVar, TokenListener.ASSIGN_INSTANCE_VAR, { n: node }, (t15) => {
|
|
23612
23513
|
if (t15 instanceof ObjectToken) {
|
|
23613
23514
|
const oVar = cvp.objPropVar(t15, node.leftNode.text);
|
|
23614
23515
|
solver.addSubsetConstraint(eVar, oVar);
|
|
23615
|
-
if (isLogical)
|
|
23616
|
-
|
|
23516
|
+
if (isLogical)
|
|
23517
|
+
solver.addSubsetConstraint(oVar, nVar);
|
|
23518
|
+
} else
|
|
23519
|
+
t15;
|
|
23617
23520
|
});
|
|
23618
23521
|
} else if (isCallNode(node.leftNode)) {
|
|
23619
23522
|
const call = node.leftNode;
|
|
@@ -23634,7 +23537,6 @@ var RubyAstVisitor = class {
|
|
|
23634
23537
|
callNode: node,
|
|
23635
23538
|
arguments: { positional: [eVar] },
|
|
23636
23539
|
result: void 0
|
|
23637
|
-
// the result of an assignment is the value assigned, not the result of the setter method
|
|
23638
23540
|
});
|
|
23639
23541
|
} else if (isConstantNode(node.leftNode) || isScopeResolutionNode(node.leftNode)) {
|
|
23640
23542
|
checkConstant(node.leftNode.text);
|
|
@@ -23642,15 +23544,18 @@ var RubyAstVisitor = class {
|
|
|
23642
23544
|
solver.addSubsetConstraint(eVar, cvp.constantVar(name));
|
|
23643
23545
|
if (isLogical)
|
|
23644
23546
|
solver.addSubsetConstraint(this.expVar(node.leftNode), nVar);
|
|
23645
|
-
} else
|
|
23547
|
+
} else
|
|
23548
|
+
a.warnUnsupported(node, `${node.leftNode.type} left-hand side in assignment`);
|
|
23646
23549
|
}
|
|
23647
23550
|
instance_variable(node) {
|
|
23648
23551
|
const { solver, cvp } = this.op;
|
|
23649
23552
|
const selfVar = cvp.selfVar(this.getSurroundingScope());
|
|
23650
23553
|
const resVar = cvp.nodeVar(node);
|
|
23651
|
-
solver.addForAllTokensConstraint(selfVar,
|
|
23652
|
-
if (t15 instanceof ObjectToken)
|
|
23653
|
-
|
|
23554
|
+
solver.addForAllTokensConstraint(selfVar, TokenListener.READ_INSTANCE_VAR, { n: node }, (t15) => {
|
|
23555
|
+
if (t15 instanceof ObjectToken)
|
|
23556
|
+
solver.addSubsetConstraint(cvp.objPropVar(t15, node.text), resVar);
|
|
23557
|
+
else
|
|
23558
|
+
t15;
|
|
23654
23559
|
});
|
|
23655
23560
|
}
|
|
23656
23561
|
class_variable(node) {
|
|
@@ -23661,16 +23566,20 @@ var RubyAstVisitor = class {
|
|
|
23661
23566
|
}
|
|
23662
23567
|
return(node) {
|
|
23663
23568
|
const { solver, cvp } = this.op;
|
|
23664
|
-
if (node.namedChildCount === 0)
|
|
23569
|
+
if (node.namedChildCount === 0)
|
|
23570
|
+
return;
|
|
23665
23571
|
const argumentsListOfReturnNode = node.firstNamedChild;
|
|
23666
23572
|
const valueToReturnNode = assertDefined(argumentsListOfReturnNode.firstNamedChild);
|
|
23667
23573
|
const resultVar = this.expVar(valueToReturnNode);
|
|
23668
23574
|
const enclosingFunction = this.scopes.findLast((n12) => {
|
|
23669
|
-
if (isMethodNode(n12) || isSingletonMethodNode(n12))
|
|
23575
|
+
if (isMethodNode(n12) || isSingletonMethodNode(n12))
|
|
23576
|
+
return true;
|
|
23670
23577
|
return (isBlockNode(n12) || isDoBlockNode(n12)) && isLambdaNode(n12.parent) && n12.parent.bodyNode.id === n12.id;
|
|
23671
23578
|
});
|
|
23672
|
-
if (enclosingFunction)
|
|
23673
|
-
|
|
23579
|
+
if (enclosingFunction)
|
|
23580
|
+
solver.addSubsetConstraint(resultVar, cvp.returnVar(enclosingFunction));
|
|
23581
|
+
else
|
|
23582
|
+
logger.warn(`Return at ${nodeLocationToString(node)} not enclosed in a function`);
|
|
23674
23583
|
}
|
|
23675
23584
|
module(node) {
|
|
23676
23585
|
return this.handleClassOrModule(node);
|
|
@@ -23679,16 +23588,7 @@ var RubyAstVisitor = class {
|
|
|
23679
23588
|
return this.handleClassOrModule(node);
|
|
23680
23589
|
}
|
|
23681
23590
|
*handleClassOrModule(node) {
|
|
23682
|
-
const {
|
|
23683
|
-
op: {
|
|
23684
|
-
solver,
|
|
23685
|
-
cvp,
|
|
23686
|
-
state: { globalNatives, constantsToNodes },
|
|
23687
|
-
tokenFactory
|
|
23688
|
-
},
|
|
23689
|
-
scopes,
|
|
23690
|
-
constantNesting
|
|
23691
|
-
} = this;
|
|
23591
|
+
const { op: { solver, cvp, state: { globalNatives, constantsToNodes }, tokenFactory }, scopes, constantNesting } = this;
|
|
23692
23592
|
const n12 = node.nameNode.text;
|
|
23693
23593
|
checkConstant(n12);
|
|
23694
23594
|
constantNesting.push(n12);
|
|
@@ -23706,20 +23606,17 @@ var RubyAstVisitor = class {
|
|
|
23706
23606
|
const sctAv = cvp.ancestorsVar(tokenFactory.createSingletonClassToken(ct));
|
|
23707
23607
|
constantNesting.pop();
|
|
23708
23608
|
assert8.strictEqual(node.superclassNode.namedChildCount, 1);
|
|
23709
|
-
solver.addForAllTokensConstraint(
|
|
23710
|
-
|
|
23711
|
-
|
|
23712
|
-
|
|
23713
|
-
|
|
23714
|
-
|
|
23715
|
-
|
|
23716
|
-
solver.addSubsetConstraint(cvp.ancestorsVar(tokenFactory.createSingletonClassToken(t15)), sctAv);
|
|
23717
|
-
} else t15;
|
|
23718
|
-
}
|
|
23719
|
-
);
|
|
23609
|
+
solver.addForAllTokensConstraint(this.expVar(node.superclassNode.firstNamedChild), TokenListener.SUPERCLASSES, { n: node }, (t15) => {
|
|
23610
|
+
if (t15 instanceof ClassToken) {
|
|
23611
|
+
solver.addSubsetConstraint(cvp.ancestorsVar(t15), av);
|
|
23612
|
+
solver.addSubsetConstraint(cvp.ancestorsVar(tokenFactory.createSingletonClassToken(t15)), sctAv);
|
|
23613
|
+
} else
|
|
23614
|
+
t15;
|
|
23615
|
+
});
|
|
23720
23616
|
yield node.superclassNode;
|
|
23721
23617
|
constantNesting.push(n12);
|
|
23722
|
-
} else
|
|
23618
|
+
} else
|
|
23619
|
+
solver.addSubsetConstraint(cvp.ancestorsVar(globalNatives.Object), av);
|
|
23723
23620
|
this.op.callMethod(av, "inherited", {
|
|
23724
23621
|
callNode: node,
|
|
23725
23622
|
caller: this.caller(node),
|
|
@@ -23735,23 +23632,17 @@ var RubyAstVisitor = class {
|
|
|
23735
23632
|
constantNesting.pop();
|
|
23736
23633
|
}
|
|
23737
23634
|
*singleton_class(node) {
|
|
23738
|
-
const {
|
|
23739
|
-
op: { solver, cvp },
|
|
23740
|
-
scopes
|
|
23741
|
-
} = this;
|
|
23635
|
+
const { op: { solver, cvp }, scopes } = this;
|
|
23742
23636
|
const defaultDefineeVar = cvp.defaultDefineeVar(node);
|
|
23743
23637
|
const selfVar = cvp.selfVar(node);
|
|
23744
|
-
solver.addForAllTokensConstraint(
|
|
23745
|
-
|
|
23746
|
-
|
|
23747
|
-
|
|
23748
|
-
|
|
23749
|
-
|
|
23750
|
-
|
|
23751
|
-
|
|
23752
|
-
} else t15;
|
|
23753
|
-
}
|
|
23754
|
-
);
|
|
23638
|
+
solver.addForAllTokensConstraint(this.expVar(node.valueNode), TokenListener.SINGLETON_CLASS, { n: node }, (t15) => {
|
|
23639
|
+
if (t15 instanceof ObjectToken) {
|
|
23640
|
+
const sct = this.op.singletonClass(t15);
|
|
23641
|
+
for (const v of [defaultDefineeVar, selfVar])
|
|
23642
|
+
solver.addTokenConstraint(sct, v);
|
|
23643
|
+
} else
|
|
23644
|
+
t15;
|
|
23645
|
+
});
|
|
23755
23646
|
yield node.valueNode;
|
|
23756
23647
|
if (node.bodyNode) {
|
|
23757
23648
|
scopes.push(node);
|
|
@@ -23762,7 +23653,8 @@ var RubyAstVisitor = class {
|
|
|
23762
23653
|
rescue_modifier(node) {
|
|
23763
23654
|
const { cvp, solver } = this.op;
|
|
23764
23655
|
const nVar = cvp.nodeVar(node);
|
|
23765
|
-
for (const n12 of [node.bodyNode, node.handlerNode])
|
|
23656
|
+
for (const n12 of [node.bodyNode, node.handlerNode])
|
|
23657
|
+
solver.addSubsetConstraint(this.expVar(n12), nVar);
|
|
23766
23658
|
}
|
|
23767
23659
|
alias(node) {
|
|
23768
23660
|
this.op.a.warnUnsupported(node, "alias");
|
|
@@ -23784,15 +23676,16 @@ var RubyAstVisitor = class {
|
|
|
23784
23676
|
if(node) {
|
|
23785
23677
|
const nVar = this.op.cvp.nodeVar(node);
|
|
23786
23678
|
for (const n12 of [node.consequenceNode, node.alternativeNode])
|
|
23787
|
-
if (n12)
|
|
23679
|
+
if (n12)
|
|
23680
|
+
this.op.solver.addSubsetConstraint(this.expVar(n12), nVar);
|
|
23788
23681
|
}
|
|
23789
23682
|
elsif(node) {
|
|
23790
23683
|
this.if(node);
|
|
23791
23684
|
}
|
|
23792
|
-
// eslint-disable-next-line unicorn/no-thenable
|
|
23793
23685
|
then(node) {
|
|
23794
23686
|
const val = node.lastNamedChild;
|
|
23795
|
-
if (val)
|
|
23687
|
+
if (val)
|
|
23688
|
+
this.op.solver.addSubsetConstraint(this.expVar(val), this.op.cvp.nodeVar(node));
|
|
23796
23689
|
}
|
|
23797
23690
|
else(node) {
|
|
23798
23691
|
this.then(node);
|
|
@@ -23800,12 +23693,14 @@ var RubyAstVisitor = class {
|
|
|
23800
23693
|
addLastNodeToReturnVarConstraint(node) {
|
|
23801
23694
|
const { solver, cvp } = this.op;
|
|
23802
23695
|
const lastNode = getLastNodeInFunction(node);
|
|
23803
|
-
if (!lastNode)
|
|
23696
|
+
if (!lastNode)
|
|
23697
|
+
return;
|
|
23804
23698
|
solver.addSubsetConstraint(this.expVar(lastNode), cvp.returnVar(node));
|
|
23805
23699
|
}
|
|
23806
23700
|
caller(node) {
|
|
23807
23701
|
const enclosingFunction = this.scopes.findLast((node2) => isFunctionNode(node2));
|
|
23808
|
-
if (!enclosingFunction)
|
|
23702
|
+
if (!enclosingFunction)
|
|
23703
|
+
return this.moduleInfo;
|
|
23809
23704
|
const caller = this.op.a.functionInfos.get(enclosingFunction);
|
|
23810
23705
|
if (!caller)
|
|
23811
23706
|
throw new Error(`Missing function info for ${nodeToString(enclosingFunction)} at ${nodeToString(node)}`);
|
|
@@ -23819,7 +23714,8 @@ var RubyAstVisitor = class {
|
|
|
23819
23714
|
const { a, state } = this.op;
|
|
23820
23715
|
const info = new FunctionInfo(name, node, this.caller(node), this.moduleInfo);
|
|
23821
23716
|
a.functionInfos.set(node, info);
|
|
23822
|
-
if (isBlockNode(node) || isDoBlockNode(node))
|
|
23717
|
+
if (isBlockNode(node) || isDoBlockNode(node))
|
|
23718
|
+
return;
|
|
23823
23719
|
const scopes = [];
|
|
23824
23720
|
for (let i = this.scopes.length - 1; i >= 0; i--) {
|
|
23825
23721
|
const s = this.scopes[i];
|
|
@@ -23830,39 +23726,46 @@ var RubyAstVisitor = class {
|
|
|
23830
23726
|
name2 = name2.slice(2);
|
|
23831
23727
|
i = 0;
|
|
23832
23728
|
}
|
|
23833
|
-
} else if (isSingletonClassNode(s))
|
|
23834
|
-
|
|
23729
|
+
} else if (isSingletonClassNode(s))
|
|
23730
|
+
name2 = `<<${fqNodeText(s.valueNode) ?? ""}`;
|
|
23731
|
+
if (name2)
|
|
23732
|
+
scopes.push(name2);
|
|
23835
23733
|
}
|
|
23836
23734
|
let fqName = name;
|
|
23837
|
-
if (isClassNode(node))
|
|
23838
|
-
|
|
23839
|
-
else
|
|
23735
|
+
if (isClassNode(node))
|
|
23736
|
+
fqName = "<constructor>";
|
|
23737
|
+
else if (isSingletonMethodNode(node))
|
|
23738
|
+
fqName = `${fqNodeText(node.objectNode) ?? "?"}.${node.nameNode.text}`;
|
|
23739
|
+
else
|
|
23740
|
+
fqName = node.nameNode.text;
|
|
23840
23741
|
state.fullyQualifiedNames.set(info, fqName = `${scopes.reverse().join("::")}#${fqName}`);
|
|
23841
23742
|
if (!validateVulnerabilityID(fqName))
|
|
23842
23743
|
assert8.fail(`Invalid fully qualified name for vulnerability matching: ${fqName}`);
|
|
23843
23744
|
}
|
|
23844
23745
|
};
|
|
23845
23746
|
function fqNodeText(n12) {
|
|
23846
|
-
if (isIdentifierNode(n12) || isConstantNode(n12) || isScopeResolutionNode(n12) || isSelfNode(n12))
|
|
23747
|
+
if (isIdentifierNode(n12) || isConstantNode(n12) || isScopeResolutionNode(n12) || isSelfNode(n12))
|
|
23748
|
+
return n12.text;
|
|
23847
23749
|
}
|
|
23848
23750
|
|
|
23849
|
-
// ../ruby-analyzer/
|
|
23751
|
+
// ../ruby-analyzer/dist/ruby-state.js
|
|
23850
23752
|
var RubyState = class {
|
|
23753
|
+
globalNatives;
|
|
23754
|
+
loadPath;
|
|
23755
|
+
constantsToNodes = /* @__PURE__ */ new Map();
|
|
23756
|
+
classInstantiations = new Array();
|
|
23757
|
+
fullyQualifiedNames = /* @__PURE__ */ new Map();
|
|
23851
23758
|
constructor(globalNatives, loadPath) {
|
|
23852
23759
|
this.globalNatives = globalNatives;
|
|
23853
23760
|
this.loadPath = loadPath;
|
|
23854
23761
|
}
|
|
23855
|
-
// Maps class constants to the syntax nodes where they are defined.
|
|
23856
|
-
// (Classes and modules can be defined and re-opened in multiple places, e.g. in different files.)
|
|
23857
|
-
constantsToNodes = /* @__PURE__ */ new Map();
|
|
23858
|
-
// Keeps track of instantiations of classes.
|
|
23859
|
-
// Used to add call edges after the analysis is done.
|
|
23860
|
-
classInstantiations = new Array();
|
|
23861
|
-
fullyQualifiedNames = /* @__PURE__ */ new Map();
|
|
23862
23762
|
};
|
|
23863
23763
|
|
|
23864
|
-
// ../ruby-analyzer/
|
|
23764
|
+
// ../ruby-analyzer/dist/ruby-analyzer.js
|
|
23865
23765
|
var RubyAnalyzer = class {
|
|
23766
|
+
solver;
|
|
23767
|
+
state;
|
|
23768
|
+
op;
|
|
23866
23769
|
constructor(solver, loadPath) {
|
|
23867
23770
|
this.solver = solver;
|
|
23868
23771
|
const constraintVarProducer = new ConstraintVarProducer();
|
|
@@ -23870,34 +23773,29 @@ var RubyAnalyzer = class {
|
|
|
23870
23773
|
this.state = new RubyState(buildNatives(solver, tokenFactory, constraintVarProducer), loadPath);
|
|
23871
23774
|
this.op = new Operations(solver, this.state, constraintVarProducer, tokenFactory);
|
|
23872
23775
|
}
|
|
23873
|
-
state;
|
|
23874
|
-
op;
|
|
23875
23776
|
async findFilesToAnalyze() {
|
|
23876
23777
|
const { rootDir } = this.solver.globalState;
|
|
23877
23778
|
const vendorDir = resolve2(rootDir, "vendor");
|
|
23878
|
-
return (await findFiles(
|
|
23879
|
-
|
|
23880
|
-
|
|
23881
|
-
|
|
23882
|
-
|
|
23883
|
-
|
|
23884
|
-
|
|
23885
|
-
|
|
23886
|
-
|
|
23887
|
-
}
|
|
23888
|
-
return false;
|
|
23889
|
-
},
|
|
23890
|
-
(dir) => dir !== vendorDir
|
|
23891
|
-
)).map((file) => [this.op.getContainingGem(dirname3(file), true), file]);
|
|
23779
|
+
return (await findFiles(rootDir, async (file) => {
|
|
23780
|
+
if (basename2(file) === "config.ru" || file.endsWith(".rb"))
|
|
23781
|
+
return true;
|
|
23782
|
+
if (/\bbin\/[^./]+$/.test(file)) {
|
|
23783
|
+
const head = Buffer.concat(await Array.fromAsync(createReadStream(file, { start: 0, end: 127 }))).toString("utf8");
|
|
23784
|
+
return /^#!.*\bruby\b/.test(head);
|
|
23785
|
+
}
|
|
23786
|
+
return false;
|
|
23787
|
+
}, (dir) => dir !== vendorDir)).map((file) => [this.op.getContainingGem(dirname3(file), true), file]);
|
|
23892
23788
|
}
|
|
23893
23789
|
async parse(filePath) {
|
|
23894
23790
|
const tree = parser.parse(await readFile(filePath, "utf8"));
|
|
23895
23791
|
if (tree.rootNode.isError) {
|
|
23896
23792
|
if (/<%.*%>/s.test(tree.rootNode.text))
|
|
23897
23793
|
logger.warn(`File '${filePath}' appears to be an ERB template. Skipping analysis.`);
|
|
23898
|
-
else
|
|
23794
|
+
else
|
|
23795
|
+
logger.error(`Failed to parse Ruby file '${filePath}'!`);
|
|
23899
23796
|
return;
|
|
23900
|
-
} else if (tree.rootNode.hasError)
|
|
23797
|
+
} else if (tree.rootNode.hasError)
|
|
23798
|
+
logger.warn(`Parsed Ruby file '${filePath}' with syntax errors!`);
|
|
23901
23799
|
return tree;
|
|
23902
23800
|
}
|
|
23903
23801
|
visit(moduleInfo, tree) {
|
|
@@ -23913,7 +23811,9 @@ var RubyAnalyzer = class {
|
|
|
23913
23811
|
patch() {
|
|
23914
23812
|
const { functionInfos } = this.op.a;
|
|
23915
23813
|
const calledFunctions = new Set(this.solver.callGraph.functionToFunction.values().flatMap((f) => f.values()));
|
|
23916
|
-
for (const moduleInfo of this.op.a.moduleInfos.values())
|
|
23814
|
+
for (const moduleInfo of this.op.a.moduleInfos.values())
|
|
23815
|
+
if (moduleInfo.isEntry)
|
|
23816
|
+
calledFunctions.add(moduleInfo);
|
|
23917
23817
|
const patched = /* @__PURE__ */ new Set();
|
|
23918
23818
|
for (const t15 of this.op.a.allTokens())
|
|
23919
23819
|
if (t15 instanceof FunctionToken && t15.kind !== "method" && (isBlockNode(t15.fun) || isDoBlockNode(t15.fun))) {
|
|
@@ -23939,7 +23839,8 @@ var RubyAnalyzer = class {
|
|
|
23939
23839
|
const vs = this.solver.globalState.options.vulnerabilities;
|
|
23940
23840
|
assert9(vs?.length);
|
|
23941
23841
|
const vulnTargets = new Map(vs.map((v) => [v, []]));
|
|
23942
|
-
for (const [fun, fqn] of this.state.fullyQualifiedNames)
|
|
23842
|
+
for (const [fun, fqn] of this.state.fullyQualifiedNames)
|
|
23843
|
+
vulnTargets.get(fqn)?.push(fun);
|
|
23943
23844
|
return vulnTargets;
|
|
23944
23845
|
}
|
|
23945
23846
|
};
|
|
@@ -23949,15 +23850,20 @@ function scopeAnalysis(tree) {
|
|
|
23949
23850
|
analyzeScope(tree.rootNode);
|
|
23950
23851
|
return bindings;
|
|
23951
23852
|
function analyzeScope(node, scope = {}) {
|
|
23952
|
-
if (!node)
|
|
23853
|
+
if (!node)
|
|
23854
|
+
return;
|
|
23953
23855
|
if (isLambdaNode(node) || isBlockNode(node) || isDoBlockNode(node)) {
|
|
23954
23856
|
scope = { ...scope };
|
|
23955
23857
|
bindParameters(node.parametersNode, scope);
|
|
23956
23858
|
} else if (isMethodNode(node) || isSingletonMethodNode(node) || isClassNode(node) || isSingletonClassNode(node) || isModuleNode(node)) {
|
|
23957
|
-
if (isSingletonMethodNode(node))
|
|
23958
|
-
|
|
23959
|
-
else if (
|
|
23960
|
-
|
|
23859
|
+
if (isSingletonMethodNode(node))
|
|
23860
|
+
analyzeScope(node.objectNode, scope);
|
|
23861
|
+
else if (isSingletonClassNode(node))
|
|
23862
|
+
analyzeScope(node.valueNode, scope);
|
|
23863
|
+
else if (isClassNode(node))
|
|
23864
|
+
analyzeScope(node.superclassNode, scope);
|
|
23865
|
+
if ("nameNode" in node)
|
|
23866
|
+
analyzeScope(node.nameNode, scope);
|
|
23961
23867
|
const newScope = {};
|
|
23962
23868
|
if ("parametersNode" in node) {
|
|
23963
23869
|
bindParameters(node.parametersNode, newScope);
|
|
@@ -23970,7 +23876,8 @@ function scopeAnalysis(tree) {
|
|
|
23970
23876
|
if (isIdentifierNode(node2))
|
|
23971
23877
|
scope[node2.text] ??= node2;
|
|
23972
23878
|
else if (isLeftAssignmentListNode(node2) || isRestAssignmentNode(node2) || isDestructuredLeftAssignmentNode(node2))
|
|
23973
|
-
for (const child of node2.namedChildren)
|
|
23879
|
+
for (const child of node2.namedChildren)
|
|
23880
|
+
aux(child);
|
|
23974
23881
|
};
|
|
23975
23882
|
aux(node.leftNode);
|
|
23976
23883
|
} else if (isRescueNode(node) && node.variableNode) {
|
|
@@ -23993,34 +23900,37 @@ function scopeAnalysis(tree) {
|
|
|
23993
23900
|
scope[node.nameNode.text] ??= node.nameNode;
|
|
23994
23901
|
else if (isIdentifierNode(node)) {
|
|
23995
23902
|
const dnode = scope[node.text];
|
|
23996
|
-
if (dnode)
|
|
23903
|
+
if (dnode)
|
|
23904
|
+
bindings.set(node, dnode);
|
|
23997
23905
|
}
|
|
23998
|
-
for (const child of node.namedChildren)
|
|
23906
|
+
for (const child of node.namedChildren)
|
|
23907
|
+
analyzeScope(child, scope);
|
|
23999
23908
|
}
|
|
24000
23909
|
function bindParameters(parameters, newScope) {
|
|
24001
|
-
if (!parameters)
|
|
23910
|
+
if (!parameters)
|
|
23911
|
+
return;
|
|
24002
23912
|
for (const param of parameters.namedChildren) {
|
|
24003
23913
|
let id;
|
|
24004
|
-
if (isIdentifierNode(param))
|
|
24005
|
-
|
|
24006
|
-
else if (
|
|
24007
|
-
|
|
24008
|
-
else if (
|
|
24009
|
-
|
|
23914
|
+
if (isIdentifierNode(param))
|
|
23915
|
+
id = param;
|
|
23916
|
+
else if (isOptionalParameterNode(param))
|
|
23917
|
+
id = param.nameNode;
|
|
23918
|
+
else if (isKeywordParameterNode(param))
|
|
23919
|
+
id = param.nameNode;
|
|
23920
|
+
else if (isBlockParameterNode(param))
|
|
23921
|
+
id = param.nameNode;
|
|
23922
|
+
else if (isDestructuredParameterNode(param))
|
|
23923
|
+
bindParameters(param, newScope);
|
|
23924
|
+
if (id)
|
|
23925
|
+
newScope[id.text] = id;
|
|
24010
23926
|
}
|
|
24011
23927
|
}
|
|
24012
23928
|
}
|
|
24013
23929
|
|
|
24014
|
-
// ../analysis-engine/
|
|
23930
|
+
// ../analysis-engine/dist/solver.js
|
|
24015
23931
|
import assert10 from "node:assert";
|
|
24016
23932
|
var Solver = class {
|
|
24017
|
-
|
|
24018
|
-
this.globalState = globalState;
|
|
24019
|
-
this.diagnostics = globalState.diagnostics;
|
|
24020
|
-
}
|
|
24021
|
-
/**
|
|
24022
|
-
* Map from listener ID to listener key. Only used for checking hash collisions on listeners.
|
|
24023
|
-
*/
|
|
23933
|
+
globalState;
|
|
24024
23934
|
listeners = /* @__PURE__ */ new Map();
|
|
24025
23935
|
callGraph = new CallGraph();
|
|
24026
23936
|
listenersProcessed = /* @__PURE__ */ new Map();
|
|
@@ -24028,19 +23938,17 @@ var Solver = class {
|
|
|
24028
23938
|
diagnostics;
|
|
24029
23939
|
nodesWithNewEdges = /* @__PURE__ */ new Set();
|
|
24030
23940
|
postponedListenersProcessed = 0;
|
|
24031
|
-
|
|
24032
|
-
|
|
24033
|
-
|
|
23941
|
+
constructor(globalState) {
|
|
23942
|
+
this.globalState = globalState;
|
|
23943
|
+
this.diagnostics = globalState.diagnostics;
|
|
23944
|
+
}
|
|
24034
23945
|
addTokenConstraint(t15, to) {
|
|
24035
|
-
if (to === void 0)
|
|
23946
|
+
if (to === void 0)
|
|
23947
|
+
return;
|
|
24036
23948
|
if (logger.isDebugEnabled())
|
|
24037
23949
|
logger.debug(`Adding constraint ${t15} \u2208 ${to}`);
|
|
24038
23950
|
this.addToken(t15, to);
|
|
24039
23951
|
}
|
|
24040
|
-
/**
|
|
24041
|
-
* Adds a single token if not already present.
|
|
24042
|
-
* Also enqueues notification of listeners and registers object properties and array entries from the constraint variable.
|
|
24043
|
-
*/
|
|
24044
23952
|
addToken(t15, toRep) {
|
|
24045
23953
|
const state = this.globalState;
|
|
24046
23954
|
if (state.addToken(t15, toRep)) {
|
|
@@ -24050,80 +23958,69 @@ var Solver = class {
|
|
|
24050
23958
|
}
|
|
24051
23959
|
return false;
|
|
24052
23960
|
}
|
|
24053
|
-
/**
|
|
24054
|
-
* Adds a set of tokens if not already present.
|
|
24055
|
-
* Also adds to worklist and notifies listeners.
|
|
24056
|
-
*/
|
|
24057
23961
|
addTokens(ts, to) {
|
|
24058
23962
|
const state = this.globalState;
|
|
24059
23963
|
state.vars.add(to);
|
|
24060
23964
|
if (ts instanceof TokenInterface) {
|
|
24061
|
-
if (state.addToken(ts, to))
|
|
23965
|
+
if (state.addToken(ts, to))
|
|
23966
|
+
this.tokenAdded(to, ts);
|
|
24062
23967
|
} else {
|
|
24063
23968
|
let ws;
|
|
24064
|
-
for (const t15 of state.addTokens(ts, to))
|
|
23969
|
+
for (const t15 of state.addTokens(ts, to))
|
|
23970
|
+
ws = this.tokenAdded(to, t15, ws);
|
|
24065
23971
|
}
|
|
24066
23972
|
}
|
|
24067
23973
|
tokenAdded(toRep, t15, ws) {
|
|
24068
23974
|
ws ??= this.varsToUnprocessedTokens.get(toRep);
|
|
24069
23975
|
ws = pushArraySingle(this.varsToUnprocessedTokens, toRep, t15, ws);
|
|
24070
23976
|
this.diagnostics.unprocessedTokensSize++;
|
|
24071
|
-
if (this.diagnostics.unprocessedTokensSize % 100 === 0)
|
|
23977
|
+
if (this.diagnostics.unprocessedTokensSize % 100 === 0)
|
|
23978
|
+
this.printDiagnostics();
|
|
24072
23979
|
return ws;
|
|
24073
23980
|
}
|
|
24074
|
-
/**
|
|
24075
|
-
* Adds a universally quantified constraint for a constraint variable.
|
|
24076
|
-
* The listener key must uniquely determine the function (including its free variables).
|
|
24077
|
-
*/
|
|
24078
23981
|
addForAllTokensConstraint(v, key, opts, listener) {
|
|
24079
|
-
if (v === void 0)
|
|
23982
|
+
if (v === void 0)
|
|
23983
|
+
return;
|
|
24080
23984
|
const lkey = { l: key, ...opts };
|
|
24081
23985
|
if (logger.isDebugEnabled())
|
|
24082
|
-
logger.debug(
|
|
24083
|
-
`Adding universally quantified constraint to ${v}: [${t5(t6(lkey, { n: nodeLocationToString, l: (l) => this.listenerName(l) })).map(([k, v2]) => `${k}: ${v2}`).join(", ")}]}`
|
|
24084
|
-
);
|
|
23986
|
+
logger.debug(`Adding universally quantified constraint to ${v}: [${t5(t6(lkey, { n: nodeLocationToString, l: (l) => this.listenerName(l) })).map(([k, v2]) => `${k}: ${v2}`).join(", ")}]}`);
|
|
24085
23987
|
this.addForAllTokensConstraintPrivate(v, this.getListenerID(lkey), listener);
|
|
24086
23988
|
}
|
|
24087
23989
|
addForAllTokensConstraintPrivate(v, id, listener) {
|
|
24088
23990
|
const m = mapGetMap(this.globalState.tokenListeners, v);
|
|
24089
23991
|
if (!m.has(id)) {
|
|
24090
|
-
for (const t15 of this.globalState.getTokens(v))
|
|
23992
|
+
for (const t15 of this.globalState.getTokens(v))
|
|
23993
|
+
this.callTokenListener(id, listener, t15);
|
|
24091
23994
|
m.set(id, listener);
|
|
24092
23995
|
this.globalState.vars.add(v);
|
|
24093
23996
|
return true;
|
|
24094
23997
|
}
|
|
24095
23998
|
return false;
|
|
24096
23999
|
}
|
|
24097
|
-
/**
|
|
24098
|
-
* Enqueues a call to a token listener if it hasn't been done before.
|
|
24099
|
-
*/
|
|
24100
24000
|
callTokenListener(id, listener, t15, now = false) {
|
|
24101
24001
|
const s = mapGetSet(this.listenersProcessed, id);
|
|
24102
24002
|
if (setAdd(s, t15)) {
|
|
24103
|
-
if (now)
|
|
24003
|
+
if (now)
|
|
24004
|
+
listener(t15);
|
|
24104
24005
|
else {
|
|
24105
24006
|
this.enqueueListenerCall([listener, t15]);
|
|
24106
24007
|
this.diagnostics.tokenListenerNotifications++;
|
|
24107
24008
|
}
|
|
24108
24009
|
}
|
|
24109
24010
|
}
|
|
24110
|
-
/**
|
|
24111
|
-
* Enqueues a listener call consisting of a listener and its argument(s).
|
|
24112
|
-
*/
|
|
24113
24011
|
enqueueListenerCall(la) {
|
|
24114
24012
|
this.globalState.postponedListenerCalls.push(la);
|
|
24115
24013
|
}
|
|
24116
|
-
/**
|
|
24117
|
-
* Provides a unique'ish ID for the given ListenerKey.
|
|
24118
|
-
*/
|
|
24119
24014
|
getListenerID(key) {
|
|
24120
24015
|
let id = 0n;
|
|
24121
24016
|
if (key.t) {
|
|
24122
24017
|
assert10(key.t.hash !== void 0);
|
|
24123
24018
|
id += BigInt(key.t.hash);
|
|
24124
24019
|
}
|
|
24125
|
-
if (key.n)
|
|
24126
|
-
|
|
24020
|
+
if (key.n)
|
|
24021
|
+
id += BigInt(strHash(nodeLocationToString(key.n)));
|
|
24022
|
+
if (key.s)
|
|
24023
|
+
id ^= BigInt(strHash(key.s));
|
|
24127
24024
|
id = id << 16n | BigInt(key.l);
|
|
24128
24025
|
this.checkListenerIDCollision(id, key);
|
|
24129
24026
|
return id;
|
|
@@ -24134,14 +24031,14 @@ var Solver = class {
|
|
|
24134
24031
|
if (x.l !== key.l || !nodeEq(x.n, key.n) || x.t !== key.t || x.s !== key.s) {
|
|
24135
24032
|
throw new Error("Hash collision in getListenerID");
|
|
24136
24033
|
}
|
|
24137
|
-
} else
|
|
24034
|
+
} else
|
|
24035
|
+
this.listeners.set(id, key);
|
|
24138
24036
|
}
|
|
24139
|
-
/**
|
|
24140
|
-
* Adds a subset constraint.
|
|
24141
|
-
*/
|
|
24142
24037
|
addSubsetConstraint(from, to) {
|
|
24143
|
-
if (from === void 0 || to === void 0)
|
|
24144
|
-
|
|
24038
|
+
if (from === void 0 || to === void 0)
|
|
24039
|
+
return;
|
|
24040
|
+
if (logger.isDebugEnabled())
|
|
24041
|
+
logger.debug(`Adding constraint ${from} \u2286 ${to}`);
|
|
24145
24042
|
this.addSubsetEdge(from, to);
|
|
24146
24043
|
}
|
|
24147
24044
|
addSubsetEdge(from, to) {
|
|
@@ -24156,9 +24053,7 @@ var Solver = class {
|
|
|
24156
24053
|
const [size, ts] = state.getTokensSize(from);
|
|
24157
24054
|
if (size > 0) {
|
|
24158
24055
|
if (logger.isDebugEnabled())
|
|
24159
|
-
logger.debug(
|
|
24160
|
-
`Worklist size: ${this.diagnostics.unprocessedTokensSize}, propagating ${size} token${size === 1 ? "" : "s"} from ${from}`
|
|
24161
|
-
);
|
|
24056
|
+
logger.debug(`Worklist size: ${this.diagnostics.unprocessedTokensSize}, propagating ${size} token${size === 1 ? "" : "s"} from ${from}`);
|
|
24162
24057
|
this.addTokens(ts, to);
|
|
24163
24058
|
this.incrementPropagations();
|
|
24164
24059
|
}
|
|
@@ -24166,23 +24061,6 @@ var Solver = class {
|
|
|
24166
24061
|
}
|
|
24167
24062
|
}
|
|
24168
24063
|
}
|
|
24169
|
-
/**
|
|
24170
|
-
* Adds an object property and notifies listeners.
|
|
24171
|
-
addObjectProperty(objVar: CV, prop: string) {
|
|
24172
|
-
const state = this.globalState;
|
|
24173
|
-
const ps = mapGetSet(state.objectProperties, objVar);
|
|
24174
|
-
if (!ps.has(prop)) {
|
|
24175
|
-
if (logger.isDebugEnabled()) logger.debug(`Adding object property ${objVar}.${prop}`);
|
|
24176
|
-
ps.add(prop);
|
|
24177
|
-
const ts = state.objectPropertyListeners.get(objVar);
|
|
24178
|
-
if (ts)
|
|
24179
|
-
for (const listener of ts.values()) {
|
|
24180
|
-
this.enqueueListenerCall([listener, prop]);
|
|
24181
|
-
this.diagnostics.objectPropertiesListenerNotifications++;
|
|
24182
|
-
}
|
|
24183
|
-
}
|
|
24184
|
-
}
|
|
24185
|
-
*/
|
|
24186
24064
|
incrementPropagations() {
|
|
24187
24065
|
this.diagnostics.propagations++;
|
|
24188
24066
|
if (this.diagnostics.propagations % 100 === 0) {
|
|
@@ -24192,17 +24070,13 @@ var Solver = class {
|
|
|
24192
24070
|
}
|
|
24193
24071
|
printDiagnostics() {
|
|
24194
24072
|
}
|
|
24195
|
-
// eslint-disable-line @typescript-eslint/no-empty-function
|
|
24196
|
-
/**
|
|
24197
|
-
* Processes all items in the worklist until a fixpoint is reached.
|
|
24198
|
-
* This notifies listeners and propagates tokens along subset edges.
|
|
24199
|
-
*/
|
|
24200
24073
|
async propagate() {
|
|
24201
24074
|
const timer = new Timer();
|
|
24202
24075
|
const { globalState: state, diagnostics: d } = this;
|
|
24203
24076
|
while (this.varsToUnprocessedTokens.size > 0 || this.nodesWithNewEdges.size > 0) {
|
|
24204
24077
|
this.nodesWithNewEdges.clear();
|
|
24205
|
-
for (const v of this.varsToUnprocessedTokens.keys())
|
|
24078
|
+
for (const v of this.varsToUnprocessedTokens.keys())
|
|
24079
|
+
this.processTokens(v);
|
|
24206
24080
|
if (state.postponedListenerCalls.length > 0) {
|
|
24207
24081
|
if (logger.isVerboseEnabled())
|
|
24208
24082
|
logger.verbose(`Processing listener calls: ${state.postponedListenerCalls.length}`);
|
|
@@ -24221,31 +24095,31 @@ var Solver = class {
|
|
|
24221
24095
|
}
|
|
24222
24096
|
d.timings.propagation += timer.elapsed();
|
|
24223
24097
|
}
|
|
24224
|
-
/**
|
|
24225
|
-
* Processes the items in the token worklist for the given constraint variable.
|
|
24226
|
-
*/
|
|
24227
24098
|
processTokens(v) {
|
|
24228
24099
|
const ts = this.varsToUnprocessedTokens.get(v);
|
|
24229
24100
|
if (ts !== void 0) {
|
|
24230
24101
|
this.varsToUnprocessedTokens.delete(v);
|
|
24231
24102
|
const size = Array.isArray(ts) ? ts.length : 1;
|
|
24232
24103
|
if (logger.isDebugEnabled())
|
|
24233
|
-
logger.debug(
|
|
24234
|
-
`Worklist size: ${this.diagnostics.unprocessedTokensSize}, propagating ${size} token${size === 1 ? "" : "s"} from ${v}`
|
|
24235
|
-
);
|
|
24104
|
+
logger.debug(`Worklist size: ${this.diagnostics.unprocessedTokensSize}, propagating ${size} token${size === 1 ? "" : "s"} from ${v}`);
|
|
24236
24105
|
this.diagnostics.unprocessedTokensSize -= size;
|
|
24237
24106
|
const state = this.globalState;
|
|
24238
24107
|
assert10(state.vars.has(v));
|
|
24239
24108
|
const s = state.subsetEdges.get(v);
|
|
24240
24109
|
if (s) {
|
|
24241
|
-
for (const to of s)
|
|
24110
|
+
for (const to of s)
|
|
24111
|
+
this.addTokens(Array.isArray(ts) ? ts : [ts], to);
|
|
24242
24112
|
this.incrementPropagations();
|
|
24243
24113
|
}
|
|
24244
24114
|
const tr = state.tokenListeners.get(v);
|
|
24245
24115
|
if (tr)
|
|
24246
24116
|
if (Array.isArray(ts))
|
|
24247
|
-
for (const t15 of ts)
|
|
24248
|
-
|
|
24117
|
+
for (const t15 of ts)
|
|
24118
|
+
for (const [id, listener] of tr)
|
|
24119
|
+
this.callTokenListener(id, listener, t15);
|
|
24120
|
+
else
|
|
24121
|
+
for (const [id, listener] of tr)
|
|
24122
|
+
this.callTokenListener(id, listener, ts);
|
|
24249
24123
|
}
|
|
24250
24124
|
}
|
|
24251
24125
|
listenersProcessedByTokenListener() {
|
|
@@ -24258,7 +24132,7 @@ var Solver = class {
|
|
|
24258
24132
|
}
|
|
24259
24133
|
};
|
|
24260
24134
|
|
|
24261
|
-
// ../ruby-analyzer/
|
|
24135
|
+
// ../ruby-analyzer/dist/types/ruby-solver.js
|
|
24262
24136
|
var RubySolver = class extends Solver {
|
|
24263
24137
|
listenerName(l) {
|
|
24264
24138
|
return TokenListener[l];
|
|
@@ -24269,11 +24143,11 @@ var RubySolver = class extends Solver {
|
|
|
24269
24143
|
import assert12 from "node:assert";
|
|
24270
24144
|
import { resolve as resolve3 } from "node:path";
|
|
24271
24145
|
|
|
24272
|
-
// ../analysis-engine/
|
|
24146
|
+
// ../analysis-engine/dist/global-state.js
|
|
24273
24147
|
import assert11 from "node:assert";
|
|
24274
24148
|
import { join as join3, relative as relative2 } from "node:path";
|
|
24275
24149
|
|
|
24276
|
-
// ../analysis-engine/
|
|
24150
|
+
// ../analysis-engine/dist/diagnostics.js
|
|
24277
24151
|
import { inspect } from "node:util";
|
|
24278
24152
|
var AnalysisDiagnostics = class {
|
|
24279
24153
|
timedOut = false;
|
|
@@ -24284,37 +24158,25 @@ var AnalysisDiagnostics = class {
|
|
|
24284
24158
|
listenerNotificationRounds = 0;
|
|
24285
24159
|
objectPropertiesListenerNotifications = 0;
|
|
24286
24160
|
timings = {
|
|
24287
|
-
...t7(
|
|
24288
|
-
|
|
24289
|
-
|
|
24290
|
-
|
|
24291
|
-
|
|
24292
|
-
|
|
24293
|
-
|
|
24294
|
-
|
|
24295
|
-
|
|
24296
|
-
],
|
|
24297
|
-
() => 0n
|
|
24298
|
-
),
|
|
24161
|
+
...t7([
|
|
24162
|
+
"listenerCall",
|
|
24163
|
+
"preAnalysis",
|
|
24164
|
+
"parsing",
|
|
24165
|
+
"constraintSetup",
|
|
24166
|
+
"propagation",
|
|
24167
|
+
"vulnAnalysis",
|
|
24168
|
+
"vulnPaths"
|
|
24169
|
+
], () => 0n),
|
|
24299
24170
|
[inspect.custom](_depth, options, f) {
|
|
24300
24171
|
return f(t9(this, nanoToMs), options);
|
|
24301
24172
|
}
|
|
24302
24173
|
};
|
|
24303
24174
|
};
|
|
24304
24175
|
|
|
24305
|
-
// ../analysis-engine/
|
|
24176
|
+
// ../analysis-engine/dist/global-state.js
|
|
24306
24177
|
var GlobalState = class _GlobalState {
|
|
24307
|
-
|
|
24308
|
-
|
|
24309
|
-
// objectPropertyListeners = new Map<CV, Map<ListenerID, (prop: string) => void>>();
|
|
24310
|
-
constructor(rootDir, options) {
|
|
24311
|
-
this.rootDir = rootDir;
|
|
24312
|
-
this.options = options;
|
|
24313
|
-
this.timeoutTimer = new Timer(options.timeout);
|
|
24314
|
-
}
|
|
24315
|
-
/**
|
|
24316
|
-
* Map from absolute paths to ModuleInfo.
|
|
24317
|
-
*/
|
|
24178
|
+
rootDir;
|
|
24179
|
+
options;
|
|
24318
24180
|
moduleInfos = /* @__PURE__ */ new Map();
|
|
24319
24181
|
packageInfos = /* @__PURE__ */ new Set();
|
|
24320
24182
|
_moduleWorklist = new Queue();
|
|
@@ -24322,7 +24184,6 @@ var GlobalState = class _GlobalState {
|
|
|
24322
24184
|
functionInfos = new NodeMap();
|
|
24323
24185
|
diagnostics = new AnalysisDiagnostics();
|
|
24324
24186
|
warningsUnsupported = new NodeMap();
|
|
24325
|
-
// TODO: Move these fields to the solver?
|
|
24326
24187
|
vars = /* @__PURE__ */ new Set();
|
|
24327
24188
|
tokens = /* @__PURE__ */ new Map();
|
|
24328
24189
|
tokenListeners = /* @__PURE__ */ new Map();
|
|
@@ -24331,16 +24192,19 @@ var GlobalState = class _GlobalState {
|
|
|
24331
24192
|
reverseSubsetEdges = /* @__PURE__ */ new Map();
|
|
24332
24193
|
numberOfSubsetEdges = 0;
|
|
24333
24194
|
static EMPTY_TOKENS_SIZE = [0, []];
|
|
24334
|
-
/**
|
|
24335
|
-
* Timeout timer.
|
|
24336
|
-
*/
|
|
24337
24195
|
timeoutTimer;
|
|
24338
24196
|
postponedListenerCalls = [];
|
|
24197
|
+
constructor(rootDir, options) {
|
|
24198
|
+
this.rootDir = rootDir;
|
|
24199
|
+
this.options = options;
|
|
24200
|
+
this.timeoutTimer = new Timer(options.timeout);
|
|
24201
|
+
}
|
|
24339
24202
|
discoverFile(packageInfo, filePath, isEntry = false) {
|
|
24340
24203
|
let moduleInfo = this.moduleInfos.get(filePath);
|
|
24341
24204
|
if (moduleInfo) {
|
|
24342
24205
|
assert11.strictEqual(packageInfo, moduleInfo.packageInfo);
|
|
24343
|
-
if (isEntry)
|
|
24206
|
+
if (isEntry)
|
|
24207
|
+
assert11(moduleInfo.isEntry);
|
|
24344
24208
|
return [moduleInfo, false];
|
|
24345
24209
|
}
|
|
24346
24210
|
moduleInfo = new ModuleInfo(relative2(join3(this.rootDir, packageInfo.dir), filePath), packageInfo, isEntry, true);
|
|
@@ -24356,70 +24220,58 @@ var GlobalState = class _GlobalState {
|
|
|
24356
24220
|
if (setAdd(warnings, message) && logger.isWarnEnabled())
|
|
24357
24221
|
logger.warn(`Unsupported: ${message} at ${nodeToString(node)}`);
|
|
24358
24222
|
}
|
|
24359
|
-
/**
|
|
24360
|
-
* Returns the tokens in the solution for the given constraint variable
|
|
24361
|
-
* (or empty if v is undefined).
|
|
24362
|
-
*/
|
|
24363
24223
|
getTokens(v) {
|
|
24364
24224
|
if (v) {
|
|
24365
24225
|
const ts = this.tokens.get(v);
|
|
24366
24226
|
if (ts) {
|
|
24367
|
-
if (ts instanceof TokenInterface)
|
|
24227
|
+
if (ts instanceof TokenInterface)
|
|
24228
|
+
return [ts];
|
|
24368
24229
|
return ts;
|
|
24369
24230
|
}
|
|
24370
24231
|
}
|
|
24371
24232
|
return [];
|
|
24372
24233
|
}
|
|
24373
|
-
/**
|
|
24374
|
-
* Returns a generator over all tokens in the solution.
|
|
24375
|
-
*/
|
|
24376
24234
|
*allTokens() {
|
|
24377
24235
|
for (const ts of this.tokens.values()) {
|
|
24378
|
-
if (ts instanceof TokenInterface)
|
|
24379
|
-
|
|
24236
|
+
if (ts instanceof TokenInterface)
|
|
24237
|
+
yield ts;
|
|
24238
|
+
else
|
|
24239
|
+
yield* ts;
|
|
24380
24240
|
}
|
|
24381
24241
|
}
|
|
24382
|
-
/**
|
|
24383
|
-
* Returns the number of tokens in the solution for the given constraint variable, and the tokens.
|
|
24384
|
-
*/
|
|
24385
24242
|
getTokensSize(v) {
|
|
24386
24243
|
if (v) {
|
|
24387
24244
|
const ts = this.tokens.get(v);
|
|
24388
24245
|
if (ts) {
|
|
24389
|
-
if (ts instanceof TokenInterface)
|
|
24246
|
+
if (ts instanceof TokenInterface)
|
|
24247
|
+
return [1, [ts]];
|
|
24390
24248
|
return [ts.size, ts];
|
|
24391
24249
|
}
|
|
24392
24250
|
}
|
|
24393
24251
|
return _GlobalState.EMPTY_TOKENS_SIZE;
|
|
24394
24252
|
}
|
|
24395
|
-
/**
|
|
24396
|
-
* Checks whether a constraint variable has a token.
|
|
24397
|
-
*/
|
|
24398
24253
|
hasToken(v, t15) {
|
|
24399
24254
|
const ts = this.tokens.get(v);
|
|
24400
|
-
if (!ts)
|
|
24401
|
-
|
|
24402
|
-
else
|
|
24403
|
-
|
|
24404
|
-
|
|
24405
|
-
|
|
24406
|
-
|
|
24407
|
-
*/
|
|
24255
|
+
if (!ts)
|
|
24256
|
+
return false;
|
|
24257
|
+
else if (ts instanceof TokenInterface)
|
|
24258
|
+
return ts === t15;
|
|
24259
|
+
else
|
|
24260
|
+
return ts.has(t15);
|
|
24261
|
+
}
|
|
24408
24262
|
addToken(t15, v) {
|
|
24409
24263
|
const ts = this.tokens.get(v);
|
|
24410
|
-
if (!ts)
|
|
24264
|
+
if (!ts)
|
|
24265
|
+
this.tokens.set(v, t15);
|
|
24411
24266
|
else if (ts instanceof TokenInterface) {
|
|
24412
|
-
if (ts === t15)
|
|
24267
|
+
if (ts === t15)
|
|
24268
|
+
return false;
|
|
24413
24269
|
this.tokens.set(v, /* @__PURE__ */ new Set([ts, t15]));
|
|
24414
|
-
} else if (!setAdd(ts, t15))
|
|
24270
|
+
} else if (!setAdd(ts, t15))
|
|
24271
|
+
return false;
|
|
24415
24272
|
this.numberOfTokens++;
|
|
24416
24273
|
return true;
|
|
24417
24274
|
}
|
|
24418
|
-
/**
|
|
24419
|
-
* Adds the given tokens to the solution for the given constraint variable.
|
|
24420
|
-
* It is assumed that the given set does not contain any duplicates.
|
|
24421
|
-
* @return the tokens that have been added, excluding those already there
|
|
24422
|
-
*/
|
|
24423
24275
|
addTokens(ts, v) {
|
|
24424
24276
|
const added = [];
|
|
24425
24277
|
let vs = this.tokens.get(v);
|
|
@@ -24435,49 +24287,46 @@ var GlobalState = class _GlobalState {
|
|
|
24435
24287
|
this.tokens.set(v, vs);
|
|
24436
24288
|
add = true;
|
|
24437
24289
|
}
|
|
24438
|
-
} else
|
|
24439
|
-
|
|
24290
|
+
} else
|
|
24291
|
+
add = setAdd(vs, t15);
|
|
24292
|
+
if (add)
|
|
24293
|
+
added.push(t15);
|
|
24440
24294
|
}
|
|
24441
24295
|
this.numberOfTokens += added.length;
|
|
24442
24296
|
return added;
|
|
24443
24297
|
}
|
|
24444
24298
|
};
|
|
24445
24299
|
|
|
24446
|
-
// ../analysis-engine/
|
|
24300
|
+
// ../analysis-engine/dist/vulnerabilities.js
|
|
24447
24301
|
function analyzeVulnerabilities(d, callGraph, targets) {
|
|
24448
24302
|
const timer = new Timer();
|
|
24449
|
-
const parents = callGraph.reachableFunctions(
|
|
24450
|
-
callGraph.functionToFunction.keys().filter((f) => f.isEntry).toArray()
|
|
24451
|
-
);
|
|
24303
|
+
const parents = callGraph.reachableFunctions(callGraph.functionToFunction.keys().filter((f) => f.isEntry).toArray());
|
|
24452
24304
|
d.timings.vulnAnalysis = timer.elapsed();
|
|
24453
24305
|
timer.reset();
|
|
24454
|
-
const results = Object.fromEntries(
|
|
24455
|
-
|
|
24456
|
-
|
|
24457
|
-
|
|
24458
|
-
|
|
24459
|
-
|
|
24460
|
-
|
|
24461
|
-
|
|
24462
|
-
|
|
24463
|
-
|
|
24464
|
-
|
|
24465
|
-
|
|
24466
|
-
|
|
24467
|
-
|
|
24468
|
-
|
|
24469
|
-
|
|
24470
|
-
|
|
24471
|
-
|
|
24472
|
-
|
|
24473
|
-
|
|
24474
|
-
|
|
24475
|
-
|
|
24476
|
-
|
|
24477
|
-
|
|
24478
|
-
];
|
|
24479
|
-
})
|
|
24480
|
-
);
|
|
24306
|
+
const results = Object.fromEntries(targets.entries().map(([vuln, funcs]) => {
|
|
24307
|
+
if (!funcs.length)
|
|
24308
|
+
return [vuln, { reachable: false, reason: "Function not found" }];
|
|
24309
|
+
const reachableFuncs = funcs.filter((f) => parents.has(f));
|
|
24310
|
+
if (!reachableFuncs.length)
|
|
24311
|
+
return [vuln, { reachable: false, reason: "Function not reachable from application code" }];
|
|
24312
|
+
return [
|
|
24313
|
+
vuln,
|
|
24314
|
+
{
|
|
24315
|
+
reachable: true,
|
|
24316
|
+
stacks: reachableFuncs.map((f) => {
|
|
24317
|
+
const stack = [];
|
|
24318
|
+
for (; f; f = parents.get(f))
|
|
24319
|
+
stack.push({
|
|
24320
|
+
package: f.packageInfo.toString(),
|
|
24321
|
+
caller: f,
|
|
24322
|
+
sourceLocation: f.loc,
|
|
24323
|
+
confidence: 1
|
|
24324
|
+
});
|
|
24325
|
+
return stack.reverse();
|
|
24326
|
+
})
|
|
24327
|
+
}
|
|
24328
|
+
];
|
|
24329
|
+
}));
|
|
24481
24330
|
d.timings.vulnPaths += timer.elapsed();
|
|
24482
24331
|
return results;
|
|
24483
24332
|
}
|
|
@@ -24619,7 +24468,7 @@ ${inspect2(globalState.diagnostics, { depth: Infinity })}`);
|
|
|
24619
24468
|
import assert14 from "node:assert";
|
|
24620
24469
|
import fs3 from "node:fs/promises";
|
|
24621
24470
|
|
|
24622
|
-
// ../utils/
|
|
24471
|
+
// ../utils/dist/graph.js
|
|
24623
24472
|
function transitiveClosure(adj, ...initial) {
|
|
24624
24473
|
const result = new Set(initial);
|
|
24625
24474
|
while (initial.length) {
|