From f71f39f2d5ff523a1749de674d444a564fc3684b Mon Sep 17 00:00:00 2001 From: Keith Cirkel Date: Wed, 28 Jun 2023 09:45:54 +0100 Subject: [PATCH] drop redundant polyfills BREAKING CHANGE --- docs/index.html | 148 ++++++++++++++++---------------- src/aggregateerror.ts | 38 -------- src/element-replacechildren.ts | 34 -------- src/index.ts | 20 ++--- src/promise-allsettled.ts | 29 ------- src/promise-any.ts | 48 ----------- src/string-replaceall.ts | 38 -------- test/aggregateerror.js | 29 ------- test/element-replacechildren.js | 26 ------ test/promise-allsettled.js | 23 ----- test/promise-any.js | 17 ---- test/string-replaceall.js | 19 ---- 12 files changed, 79 insertions(+), 390 deletions(-) delete mode 100644 src/aggregateerror.ts delete mode 100644 src/element-replacechildren.ts delete mode 100644 src/promise-allsettled.ts delete mode 100644 src/promise-any.ts delete mode 100644 src/string-replaceall.ts delete mode 100644 test/aggregateerror.js delete mode 100644 test/element-replacechildren.js delete mode 100644 test/promise-allsettled.js delete mode 100644 test/promise-any.js delete mode 100644 test/string-replaceall.js diff --git a/docs/index.html b/docs/index.html index 42a77a9..570ea3e 100644 --- a/docs/index.html +++ b/docs/index.html @@ -482,6 +482,80 @@

GitHub Feature Support Table

60+
11.0+
+ + + + String.replaceAll + + +
*
+
85+
+
85+
+
77+
+
13.1+
+
71+
+
14.0+
+ + + + + AggregateError + + +
*
+
85+
+
85+
+
79+
+
14+
+
71+
+
14.0+
+ + + + + Element.replaceChildren + + +
*
+
86+
+
86+
+
78+
+
14+
+
72+
+
14.0+
+ + + + + Promise.allSettled + + +
*
+
76+
+
79+
+
71+
+
13+
+
63+
+
12.0+
+ + + + + Promise.any + + +
*
+
85+
+
85+
+
79+
+
14+
+
71+
+
14+
+

Polyfilled Features

@@ -514,20 +588,6 @@

GitHub Feature Support Table

89+
16+
- - - - AggregateError - - -
*
-
85+
-
85+
-
79+
-
14+
-
71+
-
14.0+
- @@ -570,20 +630,6 @@

GitHub Feature Support Table

78+
16.0+
- - -
- Element.replaceChildren - - -
*
-
86+
-
86+
-
78+
-
14+
-
72+
-
14.0+
- GitHub Feature Support Table
79+
17.0+
- - -
- Promise.allSettled - - -
*
-
76+
-
79+
-
71+
-
13+
-
63+
-
12.0+
- - - - - Promise.any - - -
*
-
85+
-
85+
-
79+
-
14+
-
71+
-
14+
- @@ -686,22 +702,6 @@

GitHub Feature Support Table

34+
5.0+
- - -
- String.replaceAll - - -
*
-
85+
-
85+
-
77+
-
13.1+
-
71+
-
14.0+
- diff --git a/src/aggregateerror.ts b/src/aggregateerror.ts deleted file mode 100644 index 4ddd293..0000000 --- a/src/aggregateerror.ts +++ /dev/null @@ -1,38 +0,0 @@ -export class AggregateError extends Error { - declare errors: unknown[] - declare cause: Error | undefined - - constructor(errors: unknown[], message: string, options: {cause?: unknown} = {}) { - super(message) - Object.defineProperty(this, 'errors', { - value: Array.from(errors), - configurable: true, - writable: true, - }) - if (options.cause) { - Object.defineProperty(this, 'cause', { - value: options.cause, - configurable: true, - writable: true, - }) - } - } -} - -/*#__PURE__*/ -export function isSupported(): boolean { - return typeof globalThis.AggregateError === 'function' -} - -/*#__PURE__*/ -export function isPolyfilled(): boolean { - // @ts-expect-error `AggregateError` - return globalThis.AggregateError === AggregateError -} - -export function apply(): void { - if (!isSupported()) { - // @ts-expect-error `AggregateError` - globalThis.AggregateError = AggregateError - } -} diff --git a/src/element-replacechildren.ts b/src/element-replacechildren.ts deleted file mode 100644 index d19df44..0000000 --- a/src/element-replacechildren.ts +++ /dev/null @@ -1,34 +0,0 @@ -export function replaceChildren(this: Element | Document | DocumentFragment, ...children: Node[]) { - while (this.firstChild) this.removeChild(this.firstChild) - this.append(...children) -} - -/*#__PURE__*/ -export function isSupported(): boolean { - return ( - 'replaceChildren' in Element.prototype && - typeof Element.prototype.replaceChildren === 'function' && - 'replaceChildren' in Document.prototype && - typeof Document.prototype.replaceChildren === 'function' && - 'replaceChildren' in DocumentFragment.prototype && - typeof DocumentFragment.prototype.replaceChildren === 'function' - ) -} - -/*#__PURE__*/ -export function isPolyfilled(): boolean { - return ( - Element.prototype.replaceChildren === replaceChildren && - Document.prototype.replaceChildren === replaceChildren && - DocumentFragment.prototype.replaceChildren === replaceChildren - ) -} - -export function apply(): void { - if (!isSupported()) { - Element.prototype.replaceChildren = - Document.prototype.replaceChildren = - DocumentFragment.prototype.replaceChildren = - replaceChildren - } -} diff --git a/src/index.ts b/src/index.ts index 4805d5d..6338e2c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,18 +1,13 @@ import * as abortSignalAbort from './abortsignal-abort.js' import * as abortSignalTimeout from './abortsignal-timeout.js' -import * as aggregateError from './aggregateerror.js' import * as arrayAt from './arraylike-at.js' import * as clipboardItem from './clipboarditem.js' import * as cryptoRandomUUID from './crypto-randomuuid.js' -import * as elementReplaceChildren from './element-replacechildren.js' import * as eventAbortSignal from './event-abortsignal.js' import * as navigatorClipboard from './navigator-clipboard.js' import * as formRequestSubmit from './form-requestsubmit.js' import * as objectHasOwn from './object-hasown.js' -import * as promiseAllSettled from './promise-allsettled.js' -import * as promiseAny from './promise-any.js' import * as requestIdleCallback from './requestidlecallback.js' -import * as stringReplaceAll from './string-replaceall.js' import * as arrayFindLast from './array-findlast.js' import * as arrayFindLastIndex from './array-findlastindex.js' @@ -39,11 +34,11 @@ export const baseSupport = 'flatMap' in Array.prototype && 'trimEnd' in String.prototype && // ES2020 - //'allSettled' in Promise && // Polyfilled + 'allSettled' in Promise && 'matchAll' in String.prototype && // ES2021 - //'replaceAll' in String.prototype && // Polyfilled - // 'any' in Promise && // Polyfilled + 'replaceAll' in String.prototype && + 'any' in Promise && // ES2022 // 'at' in String.prototype && // Polyfilled // 'at' in Array.prototype && // Polyfilled @@ -51,28 +46,23 @@ export const baseSupport = // ESNext // 'abort' in AbortSignal && // Polyfilled // 'timeout' in AbortSignal && // Polyfilled - // typeof AggregateError === 'function' && // Polyfilled + typeof AggregateError === 'function' && // 'randomUUID' in crypto && // Polyfilled - // 'replaceChildren' in Element.prototype && // Polyfilled + 'replaceChildren' in Element.prototype && // 'requestIdleCallback' in window && // Polyfilled true export const polyfills = { abortSignalAbort, abortSignalTimeout, - aggregateError, arrayAt, clipboardItem, cryptoRandomUUID, - elementReplaceChildren, eventAbortSignal, navigatorClipboard, formRequestSubmit, objectHasOwn, - promiseAllSettled, - promiseAny, requestIdleCallback, - stringReplaceAll, arrayFindLast, arrayFindLastIndex, } diff --git a/src/promise-allsettled.ts b/src/promise-allsettled.ts deleted file mode 100644 index 8f9b574..0000000 --- a/src/promise-allsettled.ts +++ /dev/null @@ -1,29 +0,0 @@ -export function promiseAllSettled( - values: T, -): Promise<{-readonly [P in keyof T]: PromiseSettledResult>}> { - return Promise.all( - values.map(p => - // eslint-disable-next-line github/no-then - Promise.resolve(p).then( - (value: unknown) => ({status: 'fulfilled', value}), - (reason: unknown) => ({status: 'rejected', reason}), - ), - ), - ) as unknown as Promise<{-readonly [P in keyof T]: PromiseSettledResult>}> -} - -/*#__PURE__*/ -export function isSupported(): boolean { - return 'allSettled' in Promise && typeof Promise.allSettled === 'function' -} - -/*#__PURE__*/ -export function isPolyfilled(): boolean { - return Promise.all === promiseAllSettled -} - -export function apply(): void { - if (!isSupported()) { - Promise.allSettled = promiseAllSettled - } -} diff --git a/src/promise-any.ts b/src/promise-any.ts deleted file mode 100644 index 8a641b7..0000000 --- a/src/promise-any.ts +++ /dev/null @@ -1,48 +0,0 @@ -export function promiseAny(values: T): Promise> -export function promiseAny(values: Iterable>): Promise> -export function promiseAny(ps: Iterable>): Promise> { - return new Promise((resolve, reject) => { - let resolved = false - const promises = Array.from(ps) - const rejections: unknown[] = [] - function resolveOne(value: T) { - if (!resolved) { - resolved = true - resolve(value as Awaited) - } - } - function rejectIfDone(e: unknown) { - rejections.push(e) - if (rejections.length === promises.length) { - reject(new globalThis.AggregateError(rejections, 'All Promises rejected')) - } - } - for (const p of promises) { - // eslint-disable-next-line github/no-then - Promise.resolve(p).then(resolveOne, rejectIfDone) - } - }) -} - -declare global { - interface PromiseConstructor { - any(values: T): Promise> - any(values: Iterable>): Promise> - } -} - -/*#__PURE__*/ -export function isSupported(): boolean { - return 'any' in Promise && typeof Promise.any === 'function' -} - -/*#__PURE__*/ -export function isPolyfilled(): boolean { - return Promise.all === promiseAny -} - -export function apply(): void { - if (!isSupported()) { - Promise.any = promiseAny - } -} diff --git a/src/string-replaceall.ts b/src/string-replaceall.ts deleted file mode 100644 index 89af625..0000000 --- a/src/string-replaceall.ts +++ /dev/null @@ -1,38 +0,0 @@ -export function stringReplaceAll( - this: string, - searchValue: RegExp | string, - replaceValue: ((substring: string, ...args: unknown[]) => string) | string, -): string { - if (searchValue instanceof RegExp) return this.replace(searchValue, replaceValue as unknown as string) - let pos = -1 - let endOfLastMatch = 0 - let result = '' - if (typeof replaceValue === 'function') { - const unwrapped = replaceValue - replaceValue = () => unwrapped(searchValue, pos, this) - } - pos = this.indexOf(searchValue, pos + 1) - while (pos !== -1) { - result += this.substring(endOfLastMatch, pos) - result += searchValue.replace(searchValue, replaceValue as string) - endOfLastMatch = pos + searchValue.length - pos = this.indexOf(searchValue, pos + 1) - } - return result + this.substring(endOfLastMatch) -} - -/*#__PURE__*/ -export function isSupported(): boolean { - return 'replaceAll' in String.prototype && typeof String.prototype.replaceAll === 'function' -} - -/*#__PURE__*/ -export function isPolyfilled(): boolean { - return String.prototype.replaceAll === stringReplaceAll -} - -export function apply(): void { - if (!isSupported()) { - String.prototype.replaceAll = stringReplaceAll - } -} diff --git a/test/aggregateerror.js b/test/aggregateerror.js deleted file mode 100644 index c56583f..0000000 --- a/test/aggregateerror.js +++ /dev/null @@ -1,29 +0,0 @@ -import {AggregateError, apply, isPolyfilled, isSupported} from '../lib/aggregateerror.js' - -describe('AggregateError', () => { - it('has standard isSupported, isPolyfilled, apply API', () => { - expect(isSupported).to.be.a('function') - expect(isPolyfilled).to.be.a('function') - expect(apply).to.be.a('function') - expect(isSupported()).to.be.a('boolean') - expect(isPolyfilled()).to.equal(false) - }) - - it('returns error instance with `errors`, `message`', async () => { - expect(new AggregateError([])).to.be.instanceOf(Error) - expect(new AggregateError([])).to.be.instanceOf(AggregateError) - expect(new AggregateError([])).to.not.equal(new AggregateError([])) - expect(new AggregateError(['a', 'b'])) - .to.have.property('errors') - .eql(['a', 'b']) - expect(new AggregateError(['a', 'b'], 'hello')) - .to.have.property('message') - .eql('hello') - }) - - it('defines additional cause optional', () => { - expect(new AggregateError(['a', 'b'], 'hello', {cause: 'a cause'})) - .to.have.property('cause') - .eql('a cause') - }) -}) diff --git a/test/element-replacechildren.js b/test/element-replacechildren.js deleted file mode 100644 index 6dc2198..0000000 --- a/test/element-replacechildren.js +++ /dev/null @@ -1,26 +0,0 @@ -import {apply, isPolyfilled, isSupported, replaceChildren} from '../lib/element-replacechildren.js' - -describe('replaceChildren', () => { - it('has standard isSupported, isPolyfilled, apply API', () => { - expect(isSupported).to.be.a('function') - expect(isPolyfilled).to.be.a('function') - expect(apply).to.be.a('function') - expect(isSupported()).to.be.a('boolean') - expect(isPolyfilled()).to.equal(false) - }) - - it('replaces all Element children with given nodes', async () => { - const el = document.createElement('div') - // eslint-disable-next-line github/no-inner-html, github/unescaped-html-literal - el.innerHTML = '

Hi' - replaceChildren.call(el, 'X') - // eslint-disable-next-line github/no-inner-html - expect(el.innerHTML).to.eql('X') - const s = document.createElement('span') - // eslint-disable-next-line github/unescaped-html-literal - s.textContent = '' - replaceChildren.call(el, s) - // eslint-disable-next-line github/no-inner-html, github/unescaped-html-literal - expect(el.innerHTML).to.eql('<foo>') - }) -}) diff --git a/test/promise-allsettled.js b/test/promise-allsettled.js deleted file mode 100644 index 2c46b86..0000000 --- a/test/promise-allsettled.js +++ /dev/null @@ -1,23 +0,0 @@ -import {apply, isPolyfilled, isSupported, promiseAllSettled} from '../lib/promise-allsettled.js' - -describe('Promise.allSettled', () => { - it('has standard isSupported, isPolyfilled, apply API', () => { - expect(isSupported).to.be.a('function') - expect(isPolyfilled).to.be.a('function') - expect(apply).to.be.a('function') - expect(isSupported()).to.be.a('boolean') - expect(isPolyfilled()).to.equal(false) - }) - - it('returns list of Promise value/rejections', async () => { - expect( - // eslint-disable-next-line prefer-promise-reject-errors - await promiseAllSettled([Promise.resolve(1), Promise.reject(2), Promise.resolve(3), Promise.reject(4)]), - ).to.eql([ - {status: 'fulfilled', value: 1}, - {status: 'rejected', reason: 2}, - {status: 'fulfilled', value: 3}, - {status: 'rejected', reason: 4}, - ]) - }) -}) diff --git a/test/promise-any.js b/test/promise-any.js deleted file mode 100644 index 3def0eb..0000000 --- a/test/promise-any.js +++ /dev/null @@ -1,17 +0,0 @@ -import {apply, isPolyfilled, isSupported, promiseAny} from '../lib/promise-any.js' - -describe('promiseAny', () => { - it('has standard isSupported, isPolyfilled, apply API', () => { - expect(isSupported).to.be.a('function') - expect(isPolyfilled).to.be.a('function') - expect(apply).to.be.a('function') - expect(isSupported()).to.be.a('boolean') - expect(isPolyfilled()).to.equal(false) - }) - - it('resolves to first resolving value', async () => { - const err = new Error('nope') - expect(await promiseAny([Promise.resolve(1), Promise.resolve(2), Promise.reject(err)])).to.equal(1) - expect(await promiseAny([Promise.reject(err), Promise.resolve(1), Promise.resolve(2)])).to.equal(1) - }) -}) diff --git a/test/string-replaceall.js b/test/string-replaceall.js deleted file mode 100644 index e5381ac..0000000 --- a/test/string-replaceall.js +++ /dev/null @@ -1,19 +0,0 @@ -import {apply, isPolyfilled, isSupported, stringReplaceAll} from '../lib/string-replaceall.js' - -describe('String#replaceAll', () => { - it('has standard isSupported, isPolyfilled, apply API', () => { - expect(isSupported).to.be.a('function') - expect(isPolyfilled).to.be.a('function') - expect(apply).to.be.a('function') - expect(isSupported()).to.be.a('boolean') - expect(isPolyfilled()).to.equal(false) - }) - - it('replaces all ocurrences of a string', async () => { - expect(stringReplaceAll.call('aaa', 'a', 'bbb')).to.equal('bbbbbbbbb') - expect(stringReplaceAll.call('aaa', 'a', 'aba')).to.equal('abaabaaba') - expect(stringReplaceAll.call('_a_a_a_', 'a', 'b')).to.equal('_b_b_b_') - expect(stringReplaceAll.call('aaa', 'a', (match, i, whole) => match + i + whole)).to.equal('a0aaaa1aaaa2aaa') - expect(stringReplaceAll.call('aaa', /a/g, 'bbb')).to.equal('bbbbbbbbb') - }) -})