Skip to content

Commit be57273

Browse files
authored
Merge pull request #35 from keithamus/add-array-findlast-and-findlastindex
Add array findlast and findlastindex
2 parents ea995cc + 1018b54 commit be57273

11 files changed

+5016
-8481
lines changed

package-lock.json

+4,825-8,398
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+51-50
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,53 @@
11
{
2-
"name": "@github/browser-support",
3-
"version": "1.2.2",
4-
"description": "Polyfills and Capable Browser detection",
5-
"homepage": "https://github.github.io/browser-support",
6-
"bugs": {
7-
"url": "https://github.com/github/browser-support/issues"
8-
},
9-
"repository": {
10-
"type": "git",
11-
"url": "git+https://github.com/github/browser-support.git"
12-
},
13-
"license": "MIT",
14-
"author": "GitHub Inc.",
15-
"contributors": [
16-
"Keith Cirkel (https://keithcirkel.co.uk/)",
17-
"Kristján Oddsson <[email protected]>"
18-
],
19-
"type": "module",
20-
"main": "lib/index.js",
21-
"module": "lib/index.js",
22-
"files": [
23-
"lib"
24-
],
25-
"scripts": {
26-
"build": "tsc --build",
27-
"lint": "eslint . --ignore-path .gitignore",
28-
"pretest": "npm run build",
29-
"test": "npm run lint && karma start test/karma.config.cjs",
30-
"prepack": "npm run build",
31-
"postpublish": "npm publish --ignore-scripts --@github:registry='https://npm.pkg.github.com'"
32-
},
33-
"prettier": "@github/prettier-config",
34-
"devDependencies": {
35-
"@github/prettier-config": "^0.0.4",
36-
"@typescript-eslint/eslint-plugin": "^5.11.0",
37-
"@typescript-eslint/parser": "^5.11.0",
38-
"chai": "^4.3.0",
39-
"chromium": "^3.0.3",
40-
"eslint": "^8.8.0",
41-
"eslint-plugin-github": "^4.1.1",
42-
"karma": "^6.1.1",
43-
"karma-chai": "^0.1.0",
44-
"karma-chai-spies": "^0.1.4",
45-
"karma-chrome-launcher": "^3.1.0",
46-
"karma-mocha": "^2.0.1",
47-
"karma-mocha-reporter": "^2.2.5",
48-
"mocha": "^9.2.0",
49-
"tslib": "^2.1.0",
50-
"typescript": "^4.7.4"
51-
}
2+
"name": "@github/browser-support",
3+
"version": "1.2.2",
4+
"description": "Polyfills and Capable Browser detection",
5+
"homepage": "https://github.github.io/browser-support",
6+
"bugs": {
7+
"url": "https://github.com/github/browser-support/issues"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/github/browser-support.git"
12+
},
13+
"license": "MIT",
14+
"author": "GitHub Inc.",
15+
"contributors": [
16+
"Keith Cirkel (https://keithcirkel.co.uk/)",
17+
"Kristj\u00e1n Oddsson <[email protected]>"
18+
],
19+
"type": "module",
20+
"main": "lib/index.js",
21+
"module": "lib/index.js",
22+
"files": [
23+
"lib"
24+
],
25+
"scripts": {
26+
"build": "tsc --build",
27+
"lint": "eslint . --ignore-path .gitignore",
28+
"pretest": "npm run build",
29+
"test": "npm run lint && karma start test/karma.config.cjs",
30+
"prepack": "npm run build",
31+
"postpublish": "npm publish --ignore-scripts --@github:registry='https://npm.pkg.github.com'"
32+
},
33+
"prettier": "@github/prettier-config",
34+
"devDependencies": {
35+
"@github/prettier-config": "^0.0.4",
36+
"@types/node": "^20.3.1",
37+
"@typescript-eslint/eslint-plugin": "^5.11.0",
38+
"@typescript-eslint/parser": "^5.11.0",
39+
"chai": "^4.3.0",
40+
"chromium": "^3.0.3",
41+
"eslint": "^8.8.0",
42+
"eslint-plugin-github": "^4.1.1",
43+
"karma": "^6.1.1",
44+
"karma-chai": "^0.1.0",
45+
"karma-chai-spies": "^0.1.4",
46+
"karma-chrome-launcher": "^3.1.0",
47+
"karma-mocha": "^2.0.1",
48+
"karma-mocha-reporter": "^2.2.5",
49+
"mocha": "^9.2.0",
50+
"tslib": "^2.1.0",
51+
"typescript": "^5.1.3"
52+
}
5253
}

src/abortsignal-abort.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,16 @@ declare global {
1212

1313
/*#__PURE__*/
1414
export function isSupported(): boolean {
15-
return (
16-
'abort' in AbortSignal &&
17-
// @ts-expect-error `.abort`
18-
typeof AbortSignal.abort === 'function'
19-
)
15+
return 'abort' in AbortSignal && typeof AbortSignal.abort === 'function'
2016
}
2117

2218
/*#__PURE__*/
2319
export function isPolyfilled(): boolean {
24-
// @ts-expect-error `.abort`
2520
return AbortSignal.abort === abortSignalAbort
2621
}
2722

2823
export function apply(): void {
2924
if (!isSupported()) {
30-
// @ts-expect-error `.abort`
3125
AbortSignal.abort = abortSignalAbort
3226
}
3327
}

src/abortsignal-timeout.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,16 @@ declare global {
1212

1313
/*#__PURE__*/
1414
export function isSupported(): boolean {
15-
return (
16-
'abort' in AbortSignal &&
17-
// @ts-expect-error `.timeout`
18-
typeof AbortSignal.timeout === 'function'
19-
)
15+
return 'abort' in AbortSignal && typeof AbortSignal.timeout === 'function'
2016
}
2117

2218
/*#__PURE__*/
2319
export function isPolyfilled(): boolean {
24-
// @ts-expect-error `.timeout`
2520
return AbortSignal.timeout === abortSignalTimeout
2621
}
2722

2823
export function apply(): void {
2924
if (!isSupported()) {
30-
// @ts-expect-error `.timeout`
3125
AbortSignal.timeout = abortSignalTimeout
3226
}
3327
}

src/array-findlast.ts

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export function arrayFindLast<T>(
2+
this: T[],
3+
pred: (this: T[], value: T, i: number, array: T[]) => boolean,
4+
recv = this
5+
): T | void {
6+
for (let i = this.length; i > 0; i -= 1) {
7+
if (pred.call(recv, this[i], i, this)) return this[i]
8+
}
9+
}
10+
11+
/*#__PURE__*/
12+
export function isSupported(): boolean {
13+
return 'findLast' in Array.prototype && typeof Array.prototype.findLast === 'function'
14+
}
15+
16+
/*#__PURE__*/
17+
export function isPolyfilled(): boolean {
18+
return Array.prototype.findLast === arrayFindLast
19+
}
20+
21+
export function apply(): void {
22+
if (!isSupported()) {
23+
const defn = {value: arrayFindLast, writable: true, configurable: true}
24+
Object.defineProperty(Array.prototype, 'findLast', defn)
25+
}
26+
}

src/array-findlastindex.ts

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
export function arrayFindLastIndex<T>(
2+
this: T[],
3+
pred: (this: T[], value: T, i: number, array: T[]) => boolean,
4+
recv = this
5+
): number {
6+
for (let i = this.length; i > 0; i -= 1) {
7+
if (pred.call(recv, this[i], i, this)) return i
8+
}
9+
return -1
10+
}
11+
12+
/*#__PURE__*/
13+
export function isSupported(): boolean {
14+
return 'findLastIndex' in Array.prototype && typeof Array.prototype.findLastIndex === 'function'
15+
}
16+
17+
/*#__PURE__*/
18+
export function isPolyfilled(): boolean {
19+
return Array.prototype.findLastIndex === arrayFindLastIndex
20+
}
21+
22+
export function apply(): void {
23+
if (!isSupported()) {
24+
const defn = {
25+
value: arrayFindLastIndex,
26+
writable: true,
27+
configurable: true
28+
}
29+
Object.defineProperty(Array.prototype, 'findLastIndex', defn)
30+
}
31+
}

src/crypto-randomuuid.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export function randomUUID() {
1+
export function randomUUID(): `${string}-${string}-${string}-${string}-${string}` {
22
const buf = new Uint32Array(4)
33
crypto.getRandomValues(buf)
44
let idx = -1
@@ -7,7 +7,7 @@ export function randomUUID() {
77
const r = (buf[idx >> 3] >> ((idx % 8) * 4)) & 15
88
const v = c === 'x' ? r : (r & 0x3) | 0x8
99
return v.toString(16)
10-
})
10+
}) as `${string}-${string}-${string}-${string}-${string}`
1111
}
1212

1313
declare global {

src/index.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import * as promiseAllSettled from './promise-allsettled.js'
1313
import * as promiseAny from './promise-any.js'
1414
import * as requestIdleCallback from './requestidlecallback.js'
1515
import * as stringReplaceAll from './string-replaceall.js'
16+
import * as arrayFindLast from './array-findlast.js'
17+
import * as arrayFindLastIndex from './array-findlastindex.js'
1618

1719
export const baseSupport =
1820
typeof Blob === 'function' &&
@@ -70,7 +72,9 @@ export const polyfills = {
7072
promiseAllSettled,
7173
promiseAny,
7274
requestIdleCallback,
73-
stringReplaceAll
75+
stringReplaceAll,
76+
arrayFindLast,
77+
arrayFindLastIndex
7478
}
7579

7680
export function isSupported() {

test/array-findlast.js

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {apply, arrayFindLast, isPolyfilled, isSupported} from '../lib/array-findlast.js'
2+
3+
describe('arrayFindLast', () => {
4+
it('has standard isSupported, isPolyfilled, apply API', () => {
5+
expect(isSupported).to.be.a('function')
6+
expect(isPolyfilled).to.be.a('function')
7+
expect(apply).to.be.a('function')
8+
expect(isSupported()).to.be.a('boolean')
9+
expect(isPolyfilled()).to.equal(false)
10+
})
11+
12+
it('returns value that passes truthy', () => {
13+
expect(arrayFindLast.call([1, 2, 3], v => v === 3)).to.equal(3)
14+
const arr = [1, 2, 3]
15+
const recv = {}
16+
expect(
17+
arrayFindLast.call(
18+
arr,
19+
function (v, i, _arr) {
20+
// eslint-disable-next-line @typescript-eslint/no-invalid-this
21+
expect(this).to.equal(recv)
22+
expect(_arr).to.equal(arr)
23+
expect(v).to.equal(arr[i])
24+
},
25+
recv
26+
)
27+
)
28+
})
29+
})

test/array-findlastindex.js

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {apply, arrayFindLastIndex, isPolyfilled, isSupported} from '../lib/array-findlastindex.js'
2+
3+
describe('arrayFindLastIndex', () => {
4+
it('has standard isSupported, isPolyfilled, apply API', () => {
5+
expect(isSupported).to.be.a('function')
6+
expect(isPolyfilled).to.be.a('function')
7+
expect(apply).to.be.a('function')
8+
expect(isSupported()).to.be.a('boolean')
9+
expect(isPolyfilled()).to.equal(false)
10+
})
11+
12+
it('returns value that passes truthy', () => {
13+
expect(arrayFindLastIndex.call([1, 2, 3], v => v === 3)).to.equal(2)
14+
const arr = [1, 2, 3]
15+
const recv = {}
16+
expect(
17+
arrayFindLastIndex.call(
18+
arr,
19+
function (v, i, _arr) {
20+
// eslint-disable-next-line @typescript-eslint/no-invalid-this
21+
expect(this).to.equal(recv)
22+
expect(_arr).to.equal(arr)
23+
expect(v).to.equal(arr[i])
24+
},
25+
recv
26+
)
27+
)
28+
})
29+
})

tsconfig.json

+16-16
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
{
2-
"include": ["src"],
3-
"compilerOptions": {
4-
"baseUrl": ".",
5-
"declaration": true,
6-
"declarationMap": true,
7-
"esModuleInterop": true,
8-
"experimentalDecorators": true,
9-
"lib": ["es2021", "dom"],
10-
"module": "ESNext",
11-
"moduleResolution": "node",
12-
"noEmit": false,
13-
"outDir": "./lib",
14-
"sourceMap": true,
15-
"strict": true,
16-
"target": "ES2020"
17-
}
2+
"include": ["src"],
3+
"compilerOptions": {
4+
"baseUrl": ".",
5+
"declaration": true,
6+
"declarationMap": true,
7+
"esModuleInterop": true,
8+
"experimentalDecorators": true,
9+
"lib": ["es2023", "dom"],
10+
"module": "ESNext",
11+
"moduleResolution": "node",
12+
"noEmit": false,
13+
"outDir": "./lib",
14+
"sourceMap": true,
15+
"strict": true,
16+
"target": "ES2020"
1817
}
18+
}

0 commit comments

Comments
 (0)