Skip to content

Commit d65f853

Browse files
CopilotMSNevCopilotnev21
authored
Fix thisArg binding in polyArrFindIndex / polyArrFindLastIndex polyfills (#562)
`polyArrFindIndex` and `polyArrFindLastIndex` were using bitwise OR (`|`) when resolving callback context, which coerced object `thisArg` values and broke callback `this` binding. This updates both polyfills to use logical fallback semantics as intended. - **Polyfill callback context fix** - Replaced `thisArg | theArray` with `thisArg || theArray` in: - `lib/src/polyfills/array.ts` (`polyArrFindIndex`) - `lib/src/polyfills/array.ts` (`polyArrFindLastIndex`) - Effect: callback `this` now correctly uses the provided `thisArg`, and falls back to `theArray` only when `thisArg` is not provided/falsy. - **Regression coverage** - Added focused tests in `lib/test/src/common/polyfills/array.test.ts` for both functions to verify: - explicit `thisArg` is preserved as callback `this` - default fallback binds callback `this` to the source array ```ts // before (buggy) callbackFn[CALL](thisArg | theArray as any, value, index, theArray); // after callbackFn[CALL](thisArg || theArray as any, value, index, theArray); ``` > [!WARNING] > > <details> > <summary>Firewall rules blocked me from connecting to one or more addresses (expand for details)</summary> > > #### I tried to connect to the following addresses, but was blocked by firewall rules: > > - `accounts.google.com` > - Triggering command: `/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=network --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --crashpad-handler-pid=4244 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/karma-7608247 --change-stack-guard-on-fork=enable --shared-files=network_parent_dirs_pipe:100,v8_context_snapshot_data:101 --field-trial-handle=3,i,17861204591039112903,10939758914733537520,262144 --disable-features=PaintHolding --variations-seed-version --pseudonymization-salt-handle=7,i,16105935546789010716,16606217994416365594,4 --trace-process-track-uuid=3190708989122997041` (dns block) > - Triggering command: `/home/REDACTED/.cache/puppeteer/chrome/linux-148.0.7778.97/chrome-linux64/chrome /home/REDACTED/.cache/puppeteer/chrome/linux-148.0.7778.97/chrome-linux64/chrome --user-data-dir=/tmp/karma-7608247 --enable-automation --no-default-browser-check --no-first-run --disable-default-apps --disable-popup-blocking --disable-translate --disable-REDACTED-timer-throttling --disable-renderer-REDACTEDing --disable-device-discovery-notifications --no-sandbox --disable-gpu --disable-web-security --disable-dev-shm-usage http://localhost:9876/?id=7608247 --headless --disable-gpu --disable-dev-shm-usage --remote-debugging-port=9222` (dns block) > - Triggering command: `/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=network --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --crashpad-handler-pid=4481 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/karma-68332849 --change-stack-guard-on-fork=enable --shared-files=network_parent_dirs_pipe:100,v8_context_snapshot_data:101 --field-trial-handle=3,i,7502828240700176064,4166064653183156238,262144 --disable-features=PaintHolding --variations-seed-version --pseudonymization-salt-handle=7,i,16762107709327361543,16977408465753334385,4 --trace-process-track-uuid=3190708989122997041` (dns block) > - `clients2.google.com` > - Triggering command: `/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=network --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --crashpad-handler-pid=4244 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/karma-7608247 --change-stack-guard-on-fork=enable --shared-files=network_parent_dirs_pipe:100,v8_context_snapshot_data:101 --field-trial-handle=3,i,17861204591039112903,10939758914733537520,262144 --disable-features=PaintHolding --variations-seed-version --pseudonymization-salt-handle=7,i,16105935546789010716,16606217994416365594,4 --trace-process-track-uuid=3190708989122997041` (dns block) > - Triggering command: `/home/REDACTED/.cache/puppeteer/chrome/linux-148.0.7778.97/chrome-linux64/chrome /home/REDACTED/.cache/puppeteer/chrome/linux-148.0.7778.97/chrome-linux64/chrome --user-data-dir=/tmp/karma-7608247 --enable-automation --no-default-browser-check --no-first-run --disable-default-apps --disable-popup-blocking --disable-translate --disable-REDACTED-timer-throttling --disable-renderer-REDACTEDing --disable-device-discovery-notifications --no-sandbox --disable-gpu --disable-web-security --disable-dev-shm-usage http://localhost:9876/?id=7608247 --headless --disable-gpu --disable-dev-shm-usage --remote-debugging-port=9222` (dns block) > - Triggering command: `/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=network --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --crashpad-handler-pid=4481 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/karma-68332849 --change-stack-guard-on-fork=enable --shared-files=network_parent_dirs_pipe:100,v8_context_snapshot_data:101 --field-trial-handle=3,i,7502828240700176064,4166064653183156238,262144 --disable-features=PaintHolding --variations-seed-version --pseudonymization-salt-handle=7,i,16762107709327361543,16977408465753334385,4 --trace-process-track-uuid=3190708989122997041` (dns block) > - `redirector.gvt1.com` > - Triggering command: `/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=network --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --crashpad-handler-pid=4244 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/karma-7608247 --change-stack-guard-on-fork=enable --shared-files=network_parent_dirs_pipe:100,v8_context_snapshot_data:101 --field-trial-handle=3,i,17861204591039112903,10939758914733537520,262144 --disable-features=PaintHolding --variations-seed-version --pseudonymization-salt-handle=7,i,16105935546789010716,16606217994416365594,4 --trace-process-track-uuid=3190708989122997041` (dns block) > - Triggering command: `/home/REDACTED/.cache/puppeteer/chrome/linux-148.0.7778.97/chrome-linux64/chrome /home/REDACTED/.cache/puppeteer/chrome/linux-148.0.7778.97/chrome-linux64/chrome --user-data-dir=/tmp/karma-7608247 --enable-automation --no-default-browser-check --no-first-run --disable-default-apps --disable-popup-blocking --disable-translate --disable-REDACTED-timer-throttling --disable-renderer-REDACTEDing --disable-device-discovery-notifications --no-sandbox --disable-gpu --disable-web-security --disable-dev-shm-usage http://localhost:9876/?id=7608247 --headless --disable-gpu --disable-dev-shm-usage --remote-debugging-port=9222` (dns block) > - Triggering command: `/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=network --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --crashpad-handler-pid=4481 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/karma-68332849 --change-stack-guard-on-fork=enable --shared-files=network_parent_dirs_pipe:100,v8_context_snapshot_data:101 --field-trial-handle=3,i,7502828240700176064,4166064653183156238,262144 --disable-features=PaintHolding --variations-seed-version --pseudonymization-salt-handle=7,i,16762107709327361543,16977408465753334385,4 --trace-process-track-uuid=3190708989122997041` (dns block) > - `www.google.com` > - Triggering command: `/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=network --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --crashpad-handler-pid=4244 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/karma-7608247 --change-stack-guard-on-fork=enable --shared-files=network_parent_dirs_pipe:100,v8_context_snapshot_data:101 --field-trial-handle=3,i,17861204591039112903,10939758914733537520,262144 --disable-features=PaintHolding --variations-seed-version --pseudonymization-salt-handle=7,i,16105935546789010716,16606217994416365594,4 --trace-process-track-uuid=3190708989122997041` (dns block) > - Triggering command: `/home/REDACTED/.cache/puppeteer/chrome/linux-148.0.7778.97/chrome-linux64/chrome /home/REDACTED/.cache/puppeteer/chrome/linux-148.0.7778.97/chrome-linux64/chrome --user-data-dir=/tmp/karma-7608247 --enable-automation --no-default-browser-check --no-first-run --disable-default-apps --disable-popup-blocking --disable-translate --disable-REDACTED-timer-throttling --disable-renderer-REDACTEDing --disable-device-discovery-notifications --no-sandbox --disable-gpu --disable-web-security --disable-dev-shm-usage http://localhost:9876/?id=7608247 --headless --disable-gpu --disable-dev-shm-usage --remote-debugging-port=9222` (dns block) > - Triggering command: `/proc/self/exe /proc/self/exe --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=network --no-sandbox --disable-dev-shm-usage --use-angle=swiftshader-webgl --crashpad-handler-pid=4481 --enable-crash-reporter=, --noerrdialogs --user-data-dir=/tmp/karma-68332849 --change-stack-guard-on-fork=enable --shared-files=network_parent_dirs_pipe:100,v8_context_snapshot_data:101 --field-trial-handle=3,i,7502828240700176064,4166064653183156238,262144 --disable-features=PaintHolding --variations-seed-version --pseudonymization-salt-handle=7,i,16762107709327361543,16977408465753334385,4 --trace-process-track-uuid=3190708989122997041` (dns block) > - `www.googleapis.com` > - Triggering command: `/usr/local/bin/node node install.js` (dns block) > > If you need me to access, download, or install something from one of these locations, you can either: > > - Configure [Actions setup steps](https://gh.io/copilot/actions-setup-steps) to set up my environment, which run before the firewall is enabled > - Add the appropriate URLs or hosts to the custom allowlist in this repository's [Copilot coding agent settings](https://github.com/nevware21/ts-utils/settings/copilot/coding_agent) (admins only) > > </details> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: MSNev <54870357+MSNev@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Nev <nev@nevware21.com>
1 parent 26b4766 commit d65f853

2 files changed

Lines changed: 126 additions & 3 deletions

File tree

lib/src/polyfills/array.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { arrForEach } from "../array/forEach";
1111
import { arrIndexOf } from "../array/indexOf";
1212
import { arrMap } from "../array/map";
1313
import { arrSlice } from "../array/slice";
14-
import { isArray, isNullOrUndefined, objToString } from "../helpers/base";
14+
import { isArray, isNullOrUndefined, isStrictNullOrUndefined, objToString } from "../helpers/base";
1515
import { CALL, LENGTH } from "../internal/constants";
1616
import { iterForOf } from "../iterator/forOf";
1717

@@ -158,7 +158,7 @@ export function polyArrFind<T, E extends T>(theArray: ArrayLike<T>, callbackFn:
158158
export function polyArrFindIndex<T, E extends T>(theArray: ArrayLike<T>, callbackFn: ArrPredicateCallbackFn<T, E> | ArrPredicateCallbackFn2<T>, thisArg?: any): number {
159159
let result = -1;
160160
arrForEach(theArray, (value, index) => {
161-
if (callbackFn[CALL](thisArg | theArray as any, value, index, theArray)) {
161+
if (callbackFn[CALL](isStrictNullOrUndefined(thisArg) ? theArray as any : thisArg, value, index, theArray)) {
162162
result = index;
163163
return -1;
164164
}
@@ -272,7 +272,7 @@ export function polyArrFindLastIndex<T, E extends T>(theArray: ArrayLike<T>, cal
272272
let result = -1;
273273
let len = theArray[LENGTH] >>> 0;
274274
for (let idx = len - 1; idx >= 0; idx--) {
275-
if (idx in theArray && callbackFn[CALL](thisArg | theArray as any, theArray[idx], idx, theArray)) {
275+
if (idx in theArray && callbackFn[CALL](isStrictNullOrUndefined(thisArg) ? theArray as any : thisArg, theArray[idx], idx, theArray)) {
276276
result = idx;
277277
break;
278278
}

lib/test/src/common/polyfills/array.test.ts

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,67 @@ describe("array polyfills", () => {
143143
assert.equal(polyArrFindIndex([4, 6, 7, 9, 12], isPrime), 2);
144144
assert.equal(called, 3);
145145
});
146+
147+
it("supports callback thisArg and defaults to the array", () => {
148+
const values = [1, 2, 3];
149+
const thisArg = { match: 2 };
150+
let cbThis: any = null;
151+
152+
assert.equal(polyArrFindIndex(values, function(value) {
153+
cbThis = this;
154+
return value === this.match;
155+
}, thisArg), 1);
156+
assert.equal(cbThis, thisArg);
157+
158+
cbThis = null;
159+
assert.equal(polyArrFindIndex(values, function(value) {
160+
cbThis = this;
161+
return value === 3;
162+
}), 2);
163+
assert.equal(cbThis, values);
164+
165+
cbThis = null;
166+
assert.equal(polyArrFindIndex(values, function(value) {
167+
cbThis = this;
168+
return value === 3;
169+
}, undefined), 2);
170+
assert.equal(cbThis, values);
171+
172+
cbThis = null;
173+
assert.equal(polyArrFindIndex(values, function(value) {
174+
cbThis = this;
175+
return value === 3;
176+
}, 0), 2);
177+
assert.equal(cbThis, 0);
178+
179+
cbThis = null;
180+
assert.equal(polyArrFindIndex(values, function(value) {
181+
cbThis = this;
182+
return value === 3;
183+
}, ""), 2);
184+
assert.equal(cbThis, "");
185+
186+
cbThis = null;
187+
assert.equal(polyArrFindIndex(values, function(value) {
188+
cbThis = this;
189+
return value === 3;
190+
}, false), 2);
191+
assert.equal(cbThis, false);
192+
193+
cbThis = null;
194+
assert.equal(polyArrFindIndex(values, function(value) {
195+
cbThis = this;
196+
return value === 3;
197+
}, "undefined"), 2);
198+
assert.equal(cbThis, "undefined");
199+
200+
cbThis = null;
201+
assert.equal(polyArrFindIndex(values, function(value) {
202+
cbThis = this;
203+
return value === 3;
204+
}, "null"), 2);
205+
assert.equal(cbThis, "null");
206+
});
146207
});
147208

148209
describe("polyArrFindLast", () => {
@@ -228,6 +289,68 @@ describe("array polyfills", () => {
228289
assert.equal(polyArrFindLastIndex([4, 6, 7, 9, 12], isPrime), 2);
229290
assert.equal(called, 3);
230291
});
292+
293+
it("supports callback thisArg and defaults to the array", () => {
294+
const values = [1, 2, 3];
295+
const thisArg = { match: 2 };
296+
let cbThis: any = null;
297+
298+
assert.equal(polyArrFindLastIndex(values, function(value) {
299+
cbThis = this;
300+
return value === this.match;
301+
}, thisArg), 1);
302+
assert.equal(cbThis, thisArg);
303+
304+
cbThis = null;
305+
assert.equal(polyArrFindLastIndex(values, function(value) {
306+
cbThis = this;
307+
return value === 1;
308+
}), 0);
309+
assert.equal(cbThis, values);
310+
311+
312+
cbThis = null;
313+
assert.equal(polyArrFindLastIndex(values, function(value) {
314+
cbThis = this;
315+
return value === 1;
316+
}, undefined), 0);
317+
assert.equal(cbThis, values);
318+
319+
cbThis = null;
320+
assert.equal(polyArrFindLastIndex(values, function(value) {
321+
cbThis = this;
322+
return value === 1;
323+
}, 0), 0);
324+
assert.equal(cbThis, 0);
325+
326+
cbThis = null;
327+
assert.equal(polyArrFindLastIndex(values, function(value) {
328+
cbThis = this;
329+
return value === 1;
330+
}, ""), 0);
331+
assert.equal(cbThis, "");
332+
333+
cbThis = null;
334+
assert.equal(polyArrFindLastIndex(values, function(value) {
335+
cbThis = this;
336+
return value === 1;
337+
}, false), 0);
338+
assert.equal(cbThis, false);
339+
340+
cbThis = null;
341+
assert.equal(polyArrFindLastIndex(values, function(value) {
342+
cbThis = this;
343+
return value === 1;
344+
}, "undefined"), 0);
345+
assert.equal(cbThis, "undefined");
346+
347+
cbThis = null;
348+
assert.equal(polyArrFindLastIndex(values, function(value) {
349+
cbThis = this;
350+
return value === 1;
351+
}, "null"), 0);
352+
assert.equal(cbThis, "null");
353+
});
231354
});
232355

233356
describe("polyArrFrom", () => {

0 commit comments

Comments
 (0)