JS: Add support for Array.prototype.with

Note: This was authored by Copilot
This commit is contained in:
Asger F
2025-09-05 13:00:59 +02:00
parent ee78b7dc96
commit 429c4eac96
2 changed files with 44 additions and 0 deletions

View File

@@ -544,6 +544,25 @@ class ToSpliced extends SummarizedCallable {
}
}
class With extends SummarizedCallable {
With() { this = "Array#with" }
override InstanceCall getACallSimple() { result.getMethodName() = "with" }
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
preservesValue = true and
(
// Copy all elements from the original array to the new array
input = "Argument[this].WithArrayElement" and
output = "ReturnValue"
or
// Replace the value at the specified index
input = "Argument[1]" and
output = "ReturnValue.ArrayElement"
)
}
}
class ArrayCoercionPackage extends FunctionalPackageSummary {
ArrayCoercionPackage() { this = "ArrayCoercionPackage" }

View File

@@ -0,0 +1,25 @@
function t1() {
const arr = [1, 2, 3];
const newArr = arr.with(1, source('with.1'));
sink(newArr[1]); // $ hasValueFlow=with.1
}
function t2() {
const arr = [source('with.2.1'), 2, source('with.2.3')];
const newArr = arr.with(1, 'replaced');
sink(newArr[0]); // $ hasValueFlow=with.2.1
sink(newArr[2]); // $ hasValueFlow=with.2.3
}
function t3() {
const arr = [1, 2, 3];
const index = source('with.3.index');
const newArr = arr.with(index, 'new value');
// No assertions here as the index is tainted, not the value
}
function t4() {
const arr = [1, 2, 3];
const newArr = arr.with(1, source('with.4'));
sink(arr[1]); // This should NOT have value flow as with() returns a new array
}