[ci] yarn format

This commit is contained in:
natemoo-re 2022-03-07 21:37:50 +00:00 committed by GitHub Actions
parent f18ee36dc0
commit 63adaeec34
45 changed files with 10089 additions and 7013 deletions

View file

@ -1,12 +1,87 @@
export { AbortController, AbortSignal, Blob, ByteLengthQueuingStrategy, CanvasRenderingContext2D, CharacterData, Comment, CountQueuingStrategy, CSSStyleSheet, CustomElementRegistry, CustomEvent, DOMException, Document, DocumentFragment, Element, Event, EventTarget, File, FormData, HTMLDocument, HTMLElement, HTMLBodyElement, HTMLCanvasElement, HTMLDivElement, HTMLHeadElement, HTMLHtmlElement, HTMLImageElement, HTMLSpanElement, HTMLStyleElement, HTMLTemplateElement, HTMLUnknownElement, Headers, IntersectionObserver, Image, ImageData, MediaQueryList, MutationObserver, Node, NodeFilter, NodeIterator, OffscreenCanvas, ReadableByteStreamController, ReadableStream, ReadableStreamBYOBReader, ReadableStreamBYOBRequest, ReadableStreamDefaultController, ReadableStreamDefaultReader, Request, ResizeObserver, Response, ShadowRoot, StyleSheet, Text, TransformStream, TreeWalker, URLPattern, WritableStream, WritableStreamDefaultController, WritableStreamDefaultWriter, Window, alert, atob, btoa, cancelAnimationFrame, cancelIdleCallback, clearTimeout, fetch, requestAnimationFrame, requestIdleCallback, setTimeout, structuredClone, } from './mod.js';
export { pathToPosix } from './lib/utils';
export {
AbortController,
AbortSignal,
Blob,
ByteLengthQueuingStrategy,
CanvasRenderingContext2D,
CharacterData,
Comment,
CountQueuingStrategy,
CSSStyleSheet,
CustomElementRegistry,
CustomEvent,
DOMException,
Document,
DocumentFragment,
Element,
Event,
EventTarget,
File,
FormData,
HTMLDocument,
HTMLElement,
HTMLBodyElement,
HTMLCanvasElement,
HTMLDivElement,
HTMLHeadElement,
HTMLHtmlElement,
HTMLImageElement,
HTMLSpanElement,
HTMLStyleElement,
HTMLTemplateElement,
HTMLUnknownElement,
Headers,
IntersectionObserver,
Image,
ImageData,
MediaQueryList,
MutationObserver,
Node,
NodeFilter,
NodeIterator,
OffscreenCanvas,
ReadableByteStreamController,
ReadableStream,
ReadableStreamBYOBReader,
ReadableStreamBYOBRequest,
ReadableStreamDefaultController,
ReadableStreamDefaultReader,
Request,
ResizeObserver,
Response,
ShadowRoot,
StyleSheet,
Text,
TransformStream,
TreeWalker,
URLPattern,
WritableStream,
WritableStreamDefaultController,
WritableStreamDefaultWriter,
Window,
alert,
atob,
btoa,
cancelAnimationFrame,
cancelIdleCallback,
clearTimeout,
fetch,
requestAnimationFrame,
requestIdleCallback,
setTimeout,
structuredClone,
} from './mod.js'
export { pathToPosix } from './lib/utils'
export declare const polyfill: {
(target: any, options?: PolyfillOptions | undefined): any;
internals(target: any, name: string): any;
};
(target: any, options?: PolyfillOptions | undefined): any
internals(target: any, name: string): any
}
interface PolyfillOptions {
exclude?: string | string[];
override?: Record<string, {
(...args: any[]): any;
}>;
}
exclude?: string | string[]
override?: Record<
string,
{
(...args: any[]): any
}
>
}

File diff suppressed because one or more lines are too long

View file

@ -2,7 +2,12 @@ import { rollup } from 'rollup'
import { nodeResolve } from '@rollup/plugin-node-resolve'
import { posix as path } from 'node:path'
import { createRequire } from 'node:module'
import { readFile as nodeReadFile, rename, rm, writeFile } from 'node:fs/promises'
import {
readFile as nodeReadFile,
rename,
rm,
writeFile,
} from 'node:fs/promises'
import { default as MagicString } from 'magic-string'
import { default as alias } from '@rollup/plugin-alias'
import { default as inject } from '@rollup/plugin-inject'
@ -11,11 +16,26 @@ import { default as typescript } from '@rollup/plugin-typescript'
const readFileCache = Object.create(null)
const require = createRequire(import.meta.url)
const readFile = (/** @type {string} */ id) => readFileCache[id] || (readFileCache[id] = nodeReadFile(id, 'utf8'))
const readFile = (/** @type {string} */ id) =>
readFileCache[id] || (readFileCache[id] = nodeReadFile(id, 'utf8'))
const pathToDOMException = path.resolve('src', 'lib', 'DOMException.js')
const pathToEventTargetShim = path.join('..', '..', 'node_modules', 'event-target-shim', 'index.mjs')
const pathToStructuredClone = path.join('..', '..', 'node_modules', '@ungap', 'structured-clone', 'esm', 'index.js')
const pathToEventTargetShim = path.join(
'..',
'..',
'node_modules',
'event-target-shim',
'index.mjs'
)
const pathToStructuredClone = path.join(
'..',
'..',
'node_modules',
'@ungap',
'structured-clone',
'esm',
'index.js'
)
const plugins = [
typescript({
@ -25,38 +45,50 @@ const plugins = [
entries: [
{ find: '@ungap/structured-clone', replacement: pathToStructuredClone },
{ find: 'event-target-shim', replacement: pathToEventTargetShim },
{ find: 'event-target-shim/dist/event-target-shim.js', replacement: pathToEventTargetShim },
{ find: 'event-target-shim/dist/event-target-shim.umd.js', replacement: pathToEventTargetShim },
{
find: 'event-target-shim/dist/event-target-shim.js',
replacement: pathToEventTargetShim,
},
{
find: 'event-target-shim/dist/event-target-shim.umd.js',
replacement: pathToEventTargetShim,
},
{ find: 'node-domexception', replacement: pathToDOMException },
],
}),
nodeResolve({
dedupe: [
'net',
'node:net'
]
dedupe: ['net', 'node:net'],
}),
inject({
// import { Promise as P } from 'es6-promise'
// P: [ 'es6-promise', 'Promise' ],
'AbortController': [ 'abort-controller/dist/abort-controller.mjs', 'AbortController' ],
'Blob': [ 'fetch-blob/from.js', 'Blob' ],
'DOMException': [pathToDOMException, 'DOMException'],
'Document': [ './Document', 'Document' ],
'Element': [ './Element', 'Element' ],
'Event': [ 'event-target-shim', 'Event' ],
'EventTarget': [ 'event-target-shim', 'EventTarget' ],
'defineEventAttribute': [ 'event-target-shim', 'defineEventAttribute' ],
'HTMLElement': ['./Element', 'HTMLElement'],
'HTMLImageElement': ['./Element', 'HTMLImageElement'],
'HTMLUnknownElement': ['./Element', 'HTMLUnknownElement'],
'MediaQueryList': [ './MediaQueryList', 'MediaQueryList' ],
'Node': [ './Node', 'Node' ],
'ReadableStream': [ 'web-streams-polyfill/dist/ponyfill.es6.mjs', 'ReadableStream' ],
'ShadowRoot': [ './Node', 'ShadowRoot' ],
'Window': [ './Window', 'Window' ],
'globalThis.ReadableStream': [ 'web-streams-polyfill/dist/ponyfill.es6.mjs', 'ReadableStream' ],
AbortController: [
'abort-controller/dist/abort-controller.mjs',
'AbortController',
],
Blob: ['fetch-blob/from.js', 'Blob'],
DOMException: [pathToDOMException, 'DOMException'],
Document: ['./Document', 'Document'],
Element: ['./Element', 'Element'],
Event: ['event-target-shim', 'Event'],
EventTarget: ['event-target-shim', 'EventTarget'],
defineEventAttribute: ['event-target-shim', 'defineEventAttribute'],
HTMLElement: ['./Element', 'HTMLElement'],
HTMLImageElement: ['./Element', 'HTMLImageElement'],
HTMLUnknownElement: ['./Element', 'HTMLUnknownElement'],
MediaQueryList: ['./MediaQueryList', 'MediaQueryList'],
Node: ['./Node', 'Node'],
ReadableStream: [
'web-streams-polyfill/dist/ponyfill.es6.mjs',
'ReadableStream',
],
ShadowRoot: ['./Node', 'ShadowRoot'],
Window: ['./Window', 'Window'],
'globalThis.ReadableStream': [
'web-streams-polyfill/dist/ponyfill.es6.mjs',
'ReadableStream',
],
}),
{
async load(id) {
@ -69,36 +101,42 @@ const plugins = [
const replacements = [
// remove unused imports
[ /(^|\n)import\s+[^']+'node:(buffer|fs|path|worker_threads)'/g, `` ],
[ /const \{ stat \} = fs/g, `` ],
[/(^|\n)import\s+[^']+'node:(buffer|fs|path|worker_threads)'/g, ``],
[/const \{ stat \} = fs/g, ``],
// remove unused polyfill utils
[ /\nif \(\s*typeof Global[\W\w]+?\n\}/g, `` ],
[ /\nif \(\s*typeof window[\W\w]+?\n\}/g, `` ],
[ /\nif \(!globalThis\.ReadableStream\) \{[\W\w]+?\n\}/g, `` ],
[ /\nif \(typeof SymbolPolyfill[\W\w]+?\n\}/g, `` ],
[/\nif \(\s*typeof Global[\W\w]+?\n\}/g, ``],
[/\nif \(\s*typeof window[\W\w]+?\n\}/g, ``],
[/\nif \(!globalThis\.ReadableStream\) \{[\W\w]+?\n\}/g, ``],
[/\nif \(typeof SymbolPolyfill[\W\w]+?\n\}/g, ``],
// remove unused polyfills
[ /\nconst globals = getGlobals\(\);/g, `` ],
[ /\nconst queueMicrotask = [\W\w]+?\n\}\)\(\);/g, ``],
[ /\nconst NativeDOMException =[^;]+;/g, `` ],
[ /\nconst SymbolPolyfill\s*=[^;]+;/g, '\nconst SymbolPolyfill = Symbol;'],
[ /\n(const|let) DOMException[^;]*;/g, `let DOMException$1=DOMException` ],
[ /\nconst DOMException = globalThis.DOMException[\W\w]+?\}\)\(\)/g, `` ],
[ /\nimport DOMException from 'node-domexception'/g, `` ],
[/\nconst globals = getGlobals\(\);/g, ``],
[/\nconst queueMicrotask = [\W\w]+?\n\}\)\(\);/g, ``],
[/\nconst NativeDOMException =[^;]+;/g, ``],
[
/\nconst SymbolPolyfill\s*=[^;]+;/g,
'\nconst SymbolPolyfill = Symbol;',
],
[
/\n(const|let) DOMException[^;]*;/g,
`let DOMException$1=DOMException`,
],
[/\nconst DOMException = globalThis.DOMException[\W\w]+?\}\)\(\)/g, ``],
[/\nimport DOMException from 'node-domexception'/g, ``],
// use shared AbortController methods
[ / new DOMException\$1/g, `new DOMException` ],
[ / from 'net'/g, `from 'node:net'` ],
[ / throw createInvalidStateError/g, `throw new DOMException` ],
[ /= createAbortController/g, `= new AbortController` ],
[ /\nconst queueMicrotask = [\W\w]+?\n\}\)\(\)\;/g, `` ],
[/ new DOMException\$1/g, `new DOMException`],
[/ from 'net'/g, `from 'node:net'`],
[/ throw createInvalidStateError/g, `throw new DOMException`],
[/= createAbortController/g, `= new AbortController`],
[/\nconst queueMicrotask = [\W\w]+?\n\}\)\(\)\;/g, ``],
// remove Body.prototype.buffer deprecation notice
[ /\nBody\.prototype\.buffer[^\n]+/g, `` ],
[/\nBody\.prototype\.buffer[^\n]+/g, ``],
// remove Body.prototype.data deprecation notice
[ /\n data: \{get: deprecate[\W\w]+?\)\}/g, `` ],
[/\n data: \{get: deprecate[\W\w]+?\)\}/g, ``],
]
for (const [replacee, replacer] of replacements) {
@ -110,22 +148,24 @@ const plugins = [
const leadIndex = replaced.index
const tailIndex = replaced.index + replaced[0].length
indexes.unshift([ leadIndex, tailIndex, replacer ])
indexes.unshift([leadIndex, tailIndex, replacer])
}
}
if (indexes.length) {
const magicString = new MagicString(code)
indexes.sort(
([leadOfA], [leadOfB]) => leadOfA - leadOfB
)
indexes.sort(([leadOfA], [leadOfB]) => leadOfA - leadOfB)
for (const [leadIndex, tailindex, replacer] of indexes) {
magicString.overwrite(leadIndex, tailindex, replacer)
}
const magicMap = magicString.generateMap({ source: pathToEsm, file: pathToMap, includeContent: true })
const magicMap = magicString.generateMap({
source: pathToEsm,
file: pathToMap,
includeContent: true,
})
const modifiedEsm = magicString.toString()
const modifiedMap = magicMap.toString()
@ -182,8 +222,16 @@ async function build() {
const modDTS = await readFile('./mod.d.ts')
writeFile('mod.d.ts', modDTS.replace('\n//# sourceMappingURL=polyfill.d.ts.map', '').replace('ponyfill.js', 'mod.js'))
writeFile('apply.js', `import { polyfill } from './mod.js'\n\nexport * from './mod.js'\n\npolyfill(globalThis)\n`)
writeFile(
'mod.d.ts',
modDTS
.replace('\n//# sourceMappingURL=polyfill.d.ts.map', '')
.replace('ponyfill.js', 'mod.js')
)
writeFile(
'apply.js',
`import { polyfill } from './mod.js'\n\nexport * from './mod.js'\n\npolyfill(globalThis)\n`
)
}
}

View file

@ -2,7 +2,8 @@ import { fileURLToPath } from 'url'
export { strict as assert } from 'assert'
export const pathFrom = (...args) => fileURLToPath(args.reduce((url, bit) => new URL(bit, url), new URL('file:')))
export const pathFrom = (...args) =>
fileURLToPath(args.reduce((url, bit) => new URL(bit, url), new URL('file:')))
export const test = async (setup) => {
console.log(`Testing Node ${process.version}:`)

View file

@ -1,17 +1,60 @@
const exclusionsForHTMLElement = [ 'CustomElementsRegistry', 'HTMLElement', 'HTMLBodyElement', 'HTMLCanvasElement', 'HTMLDivElement', 'HTMLHeadElement', 'HTMLHtmlElement', 'HTMLImageElement', 'HTMLStyleElement', 'HTMLTemplateElement', 'HTMLUnknownElement', 'Image' ]
const exclusionsForElement = [ 'Element', ...exclusionsForHTMLElement ] as const
const exclusionsForDocument = [ 'CustomElementsRegistry', 'Document', 'HTMLDocument', 'document', 'customElements' ] as const
const exclusionsForNode = [ 'Node', 'DocumentFragment', 'ShadowRoot', ...exclusionsForDocument, ...exclusionsForElement ] as const
const exclusionsForEventTarget = [ 'AbortSignal', 'Event', 'CustomEvent', 'EventTarget', 'OffscreenCanvas', 'MediaQueryList', 'Window', ...exclusionsForNode ] as const
const exclusionsForEvent = [ 'AbortSignal', 'Event', 'CustomEvent', 'EventTarget', 'MediaQueryList', 'OffscreenCanvas', 'Window', ...exclusionsForNode ] as const
const exclusionsForHTMLElement = [
'CustomElementsRegistry',
'HTMLElement',
'HTMLBodyElement',
'HTMLCanvasElement',
'HTMLDivElement',
'HTMLHeadElement',
'HTMLHtmlElement',
'HTMLImageElement',
'HTMLStyleElement',
'HTMLTemplateElement',
'HTMLUnknownElement',
'Image',
]
const exclusionsForElement = ['Element', ...exclusionsForHTMLElement] as const
const exclusionsForDocument = [
'CustomElementsRegistry',
'Document',
'HTMLDocument',
'document',
'customElements',
] as const
const exclusionsForNode = [
'Node',
'DocumentFragment',
'ShadowRoot',
...exclusionsForDocument,
...exclusionsForElement,
] as const
const exclusionsForEventTarget = [
'AbortSignal',
'Event',
'CustomEvent',
'EventTarget',
'OffscreenCanvas',
'MediaQueryList',
'Window',
...exclusionsForNode,
] as const
const exclusionsForEvent = [
'AbortSignal',
'Event',
'CustomEvent',
'EventTarget',
'MediaQueryList',
'OffscreenCanvas',
'Window',
...exclusionsForNode,
] as const
export const exclusions = {
'Blob+': [ 'Blob', 'File' ],
'Blob+': ['Blob', 'File'],
'Document+': exclusionsForDocument,
'Element+': exclusionsForElement,
'Event+': exclusionsForEvent,
'EventTarget+': exclusionsForEventTarget,
'HTMLElement+': exclusionsForHTMLElement,
'Node+': exclusionsForNode,
'StyleSheet+': [ 'StyleSheet', 'CSSStyleSheet' ],
'StyleSheet+': ['StyleSheet', 'CSSStyleSheet'],
}

View file

@ -1,9 +1,15 @@
import { setTimeout as nodeSetTimeout, clearTimeout as nodeClearTimeout } from 'node:timers'
import {
setTimeout as nodeSetTimeout,
clearTimeout as nodeClearTimeout,
} from 'node:timers'
import * as _ from './utils.js'
const INTERNAL = { tick: 0, pool: new Map }
const INTERNAL = { tick: 0, pool: new Map() }
export function requestAnimationFrame<TArgs extends any[], TFunc extends (...args: TArgs) => any>(callback: TFunc): number {
export function requestAnimationFrame<
TArgs extends any[],
TFunc extends (...args: TArgs) => any
>(callback: TFunc): number {
if (!INTERNAL.pool.size) {
nodeSetTimeout(() => {
const next = _.__performance_now()

View file

@ -10,11 +10,13 @@ export class CanvasRenderingContext2D {
}
get direction(): 'ltr' | 'rtl' | 'inherit' {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'direction').direction
return _.internalsOf(this, 'CanvasRenderingContext2D', 'direction')
.direction
}
get fillStyle(): string {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'fillStyle').fillStyle
return _.internalsOf(this, 'CanvasRenderingContext2D', 'fillStyle')
.fillStyle
}
get filter(): string {
@ -22,11 +24,16 @@ export class CanvasRenderingContext2D {
}
get globalAlpha(): number {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'globalAlpha').globalAlpha
return _.internalsOf(this, 'CanvasRenderingContext2D', 'globalAlpha')
.globalAlpha
}
get globalCompositeOperation(): string {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'globalCompositeOperation').globalCompositeOperation
return _.internalsOf(
this,
'CanvasRenderingContext2D',
'globalCompositeOperation'
).globalCompositeOperation
}
get font(): string {
@ -34,11 +41,19 @@ export class CanvasRenderingContext2D {
}
get imageSmoothingEnabled(): boolean {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'imageSmoothingEnabled').imageSmoothingEnabled
return _.internalsOf(
this,
'CanvasRenderingContext2D',
'imageSmoothingEnabled'
).imageSmoothingEnabled
}
get imageSmoothingQuality(): 'low' | 'medium' | 'high' {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'imageSmoothingQuality').imageSmoothingQuality
return _.internalsOf(
this,
'CanvasRenderingContext2D',
'imageSmoothingQuality'
).imageSmoothingQuality
}
get lineCap(): 'butt' | 'round' | 'square' {
@ -46,7 +61,8 @@ export class CanvasRenderingContext2D {
}
get lineDashOffset(): number {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'lineDashOffset').lineDashOffset
return _.internalsOf(this, 'CanvasRenderingContext2D', 'lineDashOffset')
.lineDashOffset
}
get lineJoin(): 'bevel' | 'round' | 'miter' {
@ -54,39 +70,54 @@ export class CanvasRenderingContext2D {
}
get lineWidth(): number {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'lineWidth').lineWidth
return _.internalsOf(this, 'CanvasRenderingContext2D', 'lineWidth')
.lineWidth
}
get miterLimit(): number {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'miterLimit').miterLimit
return _.internalsOf(this, 'CanvasRenderingContext2D', 'miterLimit')
.miterLimit
}
get strokeStyle(): string {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'strokeStyle').strokeStyle
return _.internalsOf(this, 'CanvasRenderingContext2D', 'strokeStyle')
.strokeStyle
}
get shadowOffsetX(): number {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'shadowOffsetX').shadowOffsetX
return _.internalsOf(this, 'CanvasRenderingContext2D', 'shadowOffsetX')
.shadowOffsetX
}
get shadowOffsetY(): number {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'shadowOffsetY').shadowOffsetY
return _.internalsOf(this, 'CanvasRenderingContext2D', 'shadowOffsetY')
.shadowOffsetY
}
get shadowBlur(): number {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'shadowBlur').shadowBlur
return _.internalsOf(this, 'CanvasRenderingContext2D', 'shadowBlur')
.shadowBlur
}
get shadowColor(): string {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'shadowColor').shadowColor
return _.internalsOf(this, 'CanvasRenderingContext2D', 'shadowColor')
.shadowColor
}
get textAlign(): 'left' | 'right' | 'center' | 'start' | 'end' {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'textAlign').textAlign
return _.internalsOf(this, 'CanvasRenderingContext2D', 'textAlign')
.textAlign
}
get textBaseline(): 'top' | 'hanging' | 'middle' | 'alphabetic' | 'ideographic' | 'bottom' {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'textBaseline').textBaseline
get textBaseline():
| 'top'
| 'hanging'
| 'middle'
| 'alphabetic'
| 'ideographic'
| 'bottom' {
return _.internalsOf(this, 'CanvasRenderingContext2D', 'textBaseline')
.textBaseline
}
arc() {}
@ -104,9 +135,11 @@ export class CanvasRenderingContext2D {
/** Whether ImageData is provided. */
const hasData = _.__object_isPrototypeOf(ImageData.prototype, arg0)
const w = hasData ? (arg0 as ImageData).width : arg0 as number
const h = hasData ? (arg0 as ImageData).height : arg1 as number
const d = hasData ? (arg0 as ImageData).data : new Uint8ClampedArray(w * h * 4)
const w = hasData ? (arg0 as ImageData).width : (arg0 as number)
const h = hasData ? (arg0 as ImageData).height : (arg1 as number)
const d = hasData
? (arg0 as ImageData).data
: new Uint8ClampedArray(w * h * 4)
return new ImageData(d, w, h)
}
@ -148,8 +181,12 @@ export class CanvasRenderingContext2D {
_.allowStringTag(CanvasRenderingContext2D)
export const __createCanvasRenderingContext2D = (canvas: EventTarget): CanvasRenderingContext2D => {
const renderingContext2D = Object.create(CanvasRenderingContext2D.prototype) as CanvasRenderingContext2D
export const __createCanvasRenderingContext2D = (
canvas: EventTarget
): CanvasRenderingContext2D => {
const renderingContext2D = Object.create(
CanvasRenderingContext2D.prototype
) as CanvasRenderingContext2D
_.INTERNALS.set(renderingContext2D, {
canvas,
@ -179,4 +216,7 @@ export const __createCanvasRenderingContext2D = (canvas: EventTarget): CanvasRen
}
/** Returns whether the value is an instance of ImageData. */
const isImageData = <T>(value: T) => (Object(value).data instanceof Uint8ClampedArray) as T extends ImageData ? true : false
const isImageData = <T>(value: T) =>
(Object(value).data instanceof Uint8ClampedArray) as T extends ImageData
? true
: false

View file

@ -7,11 +7,16 @@ export class CharacterData extends Node {
} as CharacterDataInternals)
}
get data(): string {
return _.internalsOf<CharacterDataInternals>(this, 'CharacterData', 'data').data
return _.internalsOf<CharacterDataInternals>(this, 'CharacterData', 'data')
.data
}
get textContent(): string {
return _.internalsOf<CharacterDataInternals>(this, 'CharacterData', 'textContent').data
return _.internalsOf<CharacterDataInternals>(
this,
'CharacterData',
'textContent'
).data
}
}
@ -23,7 +28,11 @@ export class Text extends CharacterData {
}
get wholeText(): string {
return _.internalsOf<CharacterDataInternals>(this, 'CharacterData', 'textContent').data
return _.internalsOf<CharacterDataInternals>(
this,
'CharacterData',
'textContent'
).data
}
}

View file

@ -28,10 +28,15 @@ export type Context<T = unknown> = {
}
/** A helper type which can extract a Context value type from a Context type. */
export type ContextType<T extends Context> = T extends Context<infer Y> ? Y : never
export type ContextType<T extends Context> = T extends Context<infer Y>
? Y
: never
/** A function which creates a Context value object */
export function createContext<T>(name: string, initialValue?: T): Readonly<Context<T>> {
export function createContext<T>(
name: string,
initialValue?: T
): Readonly<Context<T>> {
return {
name,
initialValue,

View file

@ -2,14 +2,29 @@ import * as _ from './utils'
export class CustomElementRegistry {
/** Defines a new custom element using the given tag name and HTMLElement constructor. */
define(name: string, constructor: Function, options?: ElementDefinitionOptions) {
const internals = _.internalsOf<CustomElementRegistryInternals>(this, 'CustomElementRegistry', 'define')
define(
name: string,
constructor: Function,
options?: ElementDefinitionOptions
) {
const internals = _.internalsOf<CustomElementRegistryInternals>(
this,
'CustomElementRegistry',
'define'
)
name = String(name)
if (/[A-Z]/.test(name)) throw new SyntaxError('Custom element name cannot contain an uppercase ASCII letter')
if (!/^[a-z]/.test(name)) throw new SyntaxError('Custom element name must have a lowercase ASCII letter as its first character')
if (!/-/.test(name)) throw new SyntaxError('Custom element name must contain a hyphen')
if (/[A-Z]/.test(name))
throw new SyntaxError(
'Custom element name cannot contain an uppercase ASCII letter'
)
if (!/^[a-z]/.test(name))
throw new SyntaxError(
'Custom element name must have a lowercase ASCII letter as its first character'
)
if (!/-/.test(name))
throw new SyntaxError('Custom element name must contain a hyphen')
internals.constructorByName.set(name, constructor)
internals.nameByConstructor.set(constructor, name)
@ -19,7 +34,11 @@ export class CustomElementRegistry {
/** Returns the constructor associated with the given tag name. */
get(name: string) {
const internals = _.internalsOf<CustomElementRegistryInternals>(this, 'CustomElementRegistry', 'get')
const internals = _.internalsOf<CustomElementRegistryInternals>(
this,
'CustomElementRegistry',
'get'
)
name = String(name).toLowerCase()
@ -27,7 +46,11 @@ export class CustomElementRegistry {
}
getName(constructor: Function) {
const internals = _.internalsOf<CustomElementRegistryInternals>(this, 'CustomElementRegistry', 'getName')
const internals = _.internalsOf<CustomElementRegistryInternals>(
this,
'CustomElementRegistry',
'getName'
)
return internals.nameByConstructor.get(constructor)
}
@ -36,23 +59,28 @@ export class CustomElementRegistry {
_.allowStringTag(CustomElementRegistry)
interface CustomElementRegistryInternals {
constructorByName: Map<string, Function>;
nameByConstructor: Map<Function, string>;
constructorByName: Map<string, Function>
nameByConstructor: Map<Function, string>
}
interface ElementDefinitionOptions {
extends?: string | undefined;
extends?: string | undefined
}
export const initCustomElementRegistry = (target: Record<any, any>, exclude: Set<string>) => {
export const initCustomElementRegistry = (
target: Record<any, any>,
exclude: Set<string>
) => {
if (exclude.has('customElements')) return
const CustomElementRegistry = target.CustomElementRegistry || globalThis.CustomElementRegistry
const CustomElementRegistry =
target.CustomElementRegistry || globalThis.CustomElementRegistry
const customElements: CustomElementRegistry = target.customElements = Object.create(CustomElementRegistry.prototype)
const customElements: CustomElementRegistry = (target.customElements =
Object.create(CustomElementRegistry.prototype))
_.INTERNALS.set(customElements, {
constructorByName: new Map,
nameByConstructor: new Map,
constructorByName: new Map(),
nameByConstructor: new Map(),
} as CustomElementRegistryInternals)
}

View file

@ -1,7 +1,9 @@
import * as _ from './utils'
import { Event } from 'event-target-shim'
class CustomEvent<TEventType extends string = string> extends Event<TEventType> {
class CustomEvent<
TEventType extends string = string
> extends Event<TEventType> {
constructor(type: TEventType, params?: CustomEventInit) {
params = Object(params) as Required<CustomEventInit>

View file

@ -4,15 +4,27 @@ import { TreeWalker } from './TreeWalker'
export class Document extends Node {
createElement(name: string) {
const internals = _.internalsOf<DocumentInternals>(this, 'Document', 'createElement')
const internals = _.internalsOf<DocumentInternals>(
this,
'Document',
'createElement'
)
const customElementInternals: CustomElementRegistryInternals = _.INTERNALS.get(internals.target.customElements)
const customElementInternals: CustomElementRegistryInternals =
_.INTERNALS.get(internals.target.customElements)
name = String(name).toLowerCase()
const TypeOfHTMLElement = internals.constructorByName.get(name) || (customElementInternals && customElementInternals.constructorByName.get(name)) || HTMLUnknownElement
const TypeOfHTMLElement =
internals.constructorByName.get(name) ||
(customElementInternals &&
customElementInternals.constructorByName.get(name)) ||
HTMLUnknownElement
const element = Object.setPrototypeOf(new EventTarget(), TypeOfHTMLElement.prototype) as HTMLElement
const element = Object.setPrototypeOf(
new EventTarget(),
TypeOfHTMLElement.prototype
) as HTMLElement
_.INTERNALS.set(element, {
attributes: {},
@ -25,10 +37,20 @@ export class Document extends Node {
return element
}
createNodeIterator(root: Node, whatToShow: number = NodeFilter.SHOW_ALL, filter?: NodeIteratorInternals['filter']) {
createNodeIterator(
root: Node,
whatToShow: number = NodeFilter.SHOW_ALL,
filter?: NodeIteratorInternals['filter']
) {
const target = Object.create(NodeIterator.prototype)
_.INTERNALS.set(target, { filter, pointerBeforeReferenceNode: false, referenceNode: root, root, whatToShow } as NodeIteratorInternals)
_.INTERNALS.set(target, {
filter,
pointerBeforeReferenceNode: false,
referenceNode: root,
root,
whatToShow,
} as NodeIteratorInternals)
return target
}
@ -37,10 +59,20 @@ export class Document extends Node {
return new Text(data)
}
createTreeWalker(root: Node, whatToShow: number = NodeFilter.SHOW_ALL, filter?: NodeFilter, expandEntityReferences?: boolean) {
createTreeWalker(
root: Node,
whatToShow: number = NodeFilter.SHOW_ALL,
filter?: NodeFilter,
expandEntityReferences?: boolean
) {
const target = Object.create(TreeWalker.prototype)
_.INTERNALS.set(target, { filter, currentNode: root, root, whatToShow } as TreeWalkerInternals)
_.INTERNALS.set(target, {
filter,
currentNode: root,
root,
whatToShow,
} as TreeWalkerInternals)
return target
}
@ -69,7 +101,10 @@ export const initDocument = (target: Target, exclude: Set<string>) => {
const EventTarget = target.EventTarget || globalThis.EventTarget
const HTMLDocument = target.HTMLDocument || globalThis.HTMLDocument
const document: HTMLDocument = target.document = Object.setPrototypeOf(new EventTarget(), HTMLDocument.prototype)
const document: HTMLDocument = (target.document = Object.setPrototypeOf(
new EventTarget(),
HTMLDocument.prototype
))
_.INTERNALS.set(document, {
target,
@ -83,7 +118,7 @@ export const initDocument = (target: Target, exclude: Set<string>) => {
['span', target.HTMLSpanElement],
['style', target.HTMLStyleElement],
]),
nameByConstructor: new Map,
nameByConstructor: new Map(),
} as DocumentInternals)
const initElement = (name: string, Class: Function) => {
@ -102,7 +137,10 @@ export const initDocument = (target: Target, exclude: Set<string>) => {
document.body = initElement('body', target.HTMLBodyElement) as HTMLBodyElement
document.head = initElement('head', target.HTMLHeadElement) as HTMLHeadElement
document.documentElement = initElement('html', target.HTMLHtmlElement) as HTMLHtmlElement
document.documentElement = initElement(
'html',
target.HTMLHtmlElement
) as HTMLHtmlElement
}
interface DocumentInternals {
@ -120,7 +158,7 @@ interface CustomElementRegistryInternals {
}
interface ElementInternals {
attributes: { [name: string]: string },
attributes: { [name: string]: string }
localName: string
ownerDocument: Document
shadowRoot: ShadowRoot

View file

@ -21,13 +21,26 @@ export class Element extends Node {
}
attachShadow(init: Partial<ShadowRootInit>) {
if (arguments.length < 1) throw new TypeError(`Failed to execute 'attachShadow' on 'Element': 1 argument required, but only 0 present.`)
if (arguments.length < 1)
throw new TypeError(
`Failed to execute 'attachShadow' on 'Element': 1 argument required, but only 0 present.`
)
if (init !== Object(init)) throw new TypeError(`Failed to execute 'attachShadow' on 'Element': The provided value is not of type 'ShadowRootInit'.`)
if (init !== Object(init))
throw new TypeError(
`Failed to execute 'attachShadow' on 'Element': The provided value is not of type 'ShadowRootInit'.`
)
if (init.mode !== 'open' && init.mode !== 'closed') throw new TypeError(`Failed to execute 'attachShadow' on 'Element': Failed to read the 'mode' property from 'ShadowRootInit': The provided value '${init.mode}' is not a valid enum value of type ShadowRootMode.`)
if (init.mode !== 'open' && init.mode !== 'closed')
throw new TypeError(
`Failed to execute 'attachShadow' on 'Element': Failed to read the 'mode' property from 'ShadowRootInit': The provided value '${init.mode}' is not a valid enum value of type ShadowRootMode.`
)
const internals = _.internalsOf<ElementInternals>(this, 'Element', 'attachShadow')
const internals = _.internalsOf<ElementInternals>(
this,
'Element',
'attachShadow'
)
if (internals.shadowRoot) throw new Error('The operation is not supported.')
@ -36,7 +49,14 @@ export class Element extends Node {
delegatesFocus: Boolean(init.delegatesFocus),
}
internals.shadowRoot = internals.shadowRoot || (/^open$/.test(internals.shadowInit.mode as string) ? Object.setPrototypeOf(new EventTarget(), ShadowRoot.prototype) as ShadowRoot : null)
internals.shadowRoot =
internals.shadowRoot ||
(/^open$/.test(internals.shadowInit.mode as string)
? (Object.setPrototypeOf(
new EventTarget(),
ShadowRoot.prototype
) as ShadowRoot)
: null)
return internals.shadowRoot
}
@ -58,21 +78,34 @@ export class Element extends Node {
}
get shadowRoot(): ShadowRoot | null {
const internals = _.internalsOf<ElementInternals>(this, 'Element', 'shadowRoot')
const internals = _.internalsOf<ElementInternals>(
this,
'Element',
'shadowRoot'
)
return Object(internals.shadowInit).mode === 'open' ? internals.shadowRoot : null
return Object(internals.shadowInit).mode === 'open'
? internals.shadowRoot
: null
}
get localName(): string {
return _.internalsOf<ElementInternals>(this, 'Element', 'localName').localName as string
return _.internalsOf<ElementInternals>(this, 'Element', 'localName')
.localName as string
}
get nodeName(): string {
return (_.internalsOf<ElementInternals>(this, 'Element', 'nodeName').localName as string).toUpperCase()
return (
_.internalsOf<ElementInternals>(this, 'Element', 'nodeName')
.localName as string
).toUpperCase()
}
get tagName(): string {
return (_.internalsOf<ElementInternals>(this, 'Element', 'tagName').localName as string).toUpperCase()
return (
_.internalsOf<ElementInternals>(this, 'Element', 'tagName')
.localName as string
).toUpperCase()
}
}
@ -106,7 +139,7 @@ _.allowStringTag(HTMLTemplateElement)
_.allowStringTag(HTMLUnknownElement)
export interface ElementInternals {
attributes: { [name: string]: string },
attributes: { [name: string]: string }
localName?: string
shadowRoot: ShadowRoot | null
shadowInit: ShadowRootInit | void
@ -115,4 +148,4 @@ export interface ElementInternals {
export interface ShadowRootInit {
mode: 'open' | 'closed'
delegatesFocus: boolean
}
}

View file

@ -9,7 +9,8 @@ export class HTMLCanvasElement extends HTMLElement {
}
set height(value) {
_.internalsOf(this, 'HTMLCanvasElement', 'height').height = Number(value) || 0
_.internalsOf(this, 'HTMLCanvasElement', 'height').height =
Number(value) || 0
}
get width(): number {
@ -24,8 +25,14 @@ export class HTMLCanvasElement extends HTMLElement {
return null
}
getContext(contextType: PredefinedContextId): CanvasRenderingContext2D | null {
const internals = _.internalsOf<HTMLCanvasElementInternals>(this, 'HTMLCanvasElement', 'getContext')
getContext(
contextType: PredefinedContextId
): CanvasRenderingContext2D | null {
const internals = _.internalsOf<HTMLCanvasElementInternals>(
this,
'HTMLCanvasElement',
'getContext'
)
switch (contextType) {
case '2d':
@ -54,4 +61,9 @@ interface HTMLCanvasElementInternals {
renderingContext2D: CanvasRenderingContext2D
}
type PredefinedContextId = '2d' | 'bitmaprenderer' | 'webgl' | 'webgl2' | 'webgpu'
type PredefinedContextId =
| '2d'
| 'bitmaprenderer'
| 'webgl'
| 'webgl2'
| 'webgpu'

View file

@ -1,9 +1,15 @@
import { setTimeout as nodeSetTimeout, clearTimeout as nodeClearTimeout } from 'node:timers'
import {
setTimeout as nodeSetTimeout,
clearTimeout as nodeClearTimeout,
} from 'node:timers'
import * as _ from './utils.js'
const INTERNAL = { tick: 0, pool: new Map }
const INTERNAL = { tick: 0, pool: new Map() }
export function requestIdleCallback<TArgs extends any[], TFunc extends (...args: TArgs) => any>(callback: TFunc): number {
export function requestIdleCallback<
TArgs extends any[],
TFunc extends (...args: TArgs) => any
>(callback: TFunc): number {
if (!INTERNAL.pool.size) {
nodeSetTimeout(() => {
const next = _.__performance_now()

View file

@ -1,20 +1,36 @@
import * as _ from './utils'
export class ImageData {
constructor(width: number, height: number);
constructor(width: number, height: number, settings: ImageDataSettings);
constructor(data: Uint8ClampedArray, width: number);
constructor(data: Uint8ClampedArray, width: number, height: number);
constructor(data: Uint8ClampedArray, width: number, height: number, settings: ImageDataSettings);
constructor(width: number, height: number)
constructor(width: number, height: number, settings: ImageDataSettings)
constructor(data: Uint8ClampedArray, width: number)
constructor(data: Uint8ClampedArray, width: number, height: number)
constructor(
data: Uint8ClampedArray,
width: number,
height: number,
settings: ImageDataSettings
)
constructor(arg0: number | Uint8ClampedArray, arg1: number, ...args: [] | [number] | [ImageDataSettings] | [number, ImageDataSettings]) {
if (arguments.length < 2) throw new TypeError(`Failed to construct 'ImageData': 2 arguments required.`)
constructor(
arg0: number | Uint8ClampedArray,
arg1: number,
...args: [] | [number] | [ImageDataSettings] | [number, ImageDataSettings]
) {
if (arguments.length < 2)
throw new TypeError(
`Failed to construct 'ImageData': 2 arguments required.`
)
/** Whether Uint8ClampedArray data is provided. */
const hasData = _.__object_isPrototypeOf(Uint8ClampedArray.prototype, arg0)
/** Image data, either provided or calculated. */
const d = hasData ? arg0 as Uint8ClampedArray : new Uint8ClampedArray(asNumber(arg0, 'width') * asNumber(arg1, 'height') * 4)
const d = hasData
? (arg0 as Uint8ClampedArray)
: new Uint8ClampedArray(
asNumber(arg0, 'width') * asNumber(arg1, 'height') * 4
)
/** Image width. */
const w = asNumber(hasData ? arg1 : arg0, 'width')
@ -23,23 +39,42 @@ export class ImageData {
const h = d.length / w / 4
/** Image color space. */
const c = String(Object(hasData ? args[1] : args[0]).colorSpace || 'srgb') as PredefinedColorSpace
const c = String(
Object(hasData ? args[1] : args[0]).colorSpace || 'srgb'
) as PredefinedColorSpace
// throw if a provided height does not match the calculated height
if (args.length && asNumber(args[0], 'height') !== h) throw new DOMException('height is not equal to (4 * width * height)', 'IndexSizeError')
if (args.length && asNumber(args[0], 'height') !== h)
throw new DOMException(
'height is not equal to (4 * width * height)',
'IndexSizeError'
)
// throw if a provided colorspace does not match a known colorspace
if (c !== 'srgb' && c !== 'rec2020' && c !== 'display-p3') throw new TypeError('colorSpace is not known value')
if (c !== 'srgb' && c !== 'rec2020' && c !== 'display-p3')
throw new TypeError('colorSpace is not known value')
Object.defineProperty(this, 'data', { configurable: true, enumerable: true, value: d })
Object.defineProperty(this, 'data', {
configurable: true,
enumerable: true,
value: d,
})
_.INTERNALS.set(this, { width: w, height: h, colorSpace: c } as ImageDataInternals)
_.INTERNALS.set(this, {
width: w,
height: h,
colorSpace: c,
} as ImageDataInternals)
}
get data(): Uint8ClampedArray {
_.internalsOf<ImageDataInternals>(this, 'ImageData', 'data')
return (Object.getOwnPropertyDescriptor(this, 'data') as { value: Uint8ClampedArray }).value
return (
Object.getOwnPropertyDescriptor(this, 'data') as {
value: Uint8ClampedArray
}
).value
}
get width(): ImageDataInternals['width'] {
@ -57,7 +92,8 @@ _.allowStringTag(ImageData)
const asNumber = (value: any, axis: string): number => {
value = Number(value) || 0
if (value === 0) throw new TypeError(`The source ${axis} is zero or not a number.`)
if (value === 0)
throw new TypeError(`The source ${axis} is zero or not a number.`)
return value
}

View file

@ -19,7 +19,10 @@ export const initMediaQueryList = (target: Target, exclude: Set<string>) => {
const MediaQueryList = target.MediaQueryList || globalThis.MediaQueryList
target.matchMedia = function matchMedia(media: string) {
const mql = Object.setPrototypeOf(new EventTarget(), MediaQueryList.prototype) as MediaQueryList
const mql = Object.setPrototypeOf(
new EventTarget(),
MediaQueryList.prototype
) as MediaQueryList
_.INTERNALS.set(mql, {
matches: false,

View file

@ -71,8 +71,11 @@ export class Node extends EventTarget {
return null
}
[Symbol.for('nodejs.util.inspect.custom')](depth: number, options: Record<string, any>) {
return `${this.constructor.name}`;
[Symbol.for('nodejs.util.inspect.custom')](
depth: number,
options: Record<string, any>
) {
return `${this.constructor.name}`
}
}
@ -88,28 +91,31 @@ export class ShadowRoot extends DocumentFragment {
}
}
export const NodeFilter = Object.assign({
NodeFilter() {
throw new TypeError('Illegal constructor')
export const NodeFilter = Object.assign(
{
NodeFilter() {
throw new TypeError('Illegal constructor')
},
}.NodeFilter,
{
FILTER_ACCEPT: 1,
FILTER_REJECT: 2,
FILTER_SKIP: 3,
SHOW_ALL: 4294967295,
SHOW_ELEMENT: 1,
SHOW_ATTRIBUTE: 2,
SHOW_TEXT: 4,
SHOW_CDATA_SECTION: 8,
SHOW_ENTITY_REFERENCE: 16,
SHOW_ENTITY: 32,
SHOW_PROCESSING_INSTRUCTION: 64,
SHOW_COMMENT: 128,
SHOW_DOCUMENT: 256,
SHOW_DOCUMENT_TYPE: 512,
SHOW_DOCUMENT_FRAGMENT: 1024,
SHOW_NOTATION: 2048,
}
}.NodeFilter, {
FILTER_ACCEPT: 1,
FILTER_REJECT: 2,
FILTER_SKIP: 3,
SHOW_ALL: 4294967295,
SHOW_ELEMENT: 1,
SHOW_ATTRIBUTE: 2,
SHOW_TEXT: 4,
SHOW_CDATA_SECTION: 8,
SHOW_ENTITY_REFERENCE: 16,
SHOW_ENTITY: 32,
SHOW_PROCESSING_INSTRUCTION: 64,
SHOW_COMMENT: 128,
SHOW_DOCUMENT: 256,
SHOW_DOCUMENT_TYPE: 512,
SHOW_DOCUMENT_FRAGMENT: 1024,
SHOW_NOTATION: 2048,
})
)
export class NodeIterator {
nextNode(): Node | null {
@ -121,27 +127,47 @@ export class NodeIterator {
}
get filter(): NodeFilter {
const internals = _.internalsOf<NodeIteratorInternals>(this, 'NodeIterator', 'filter')
const internals = _.internalsOf<NodeIteratorInternals>(
this,
'NodeIterator',
'filter'
)
return internals.filter
}
get pointerBeforeReferenceNode(): boolean {
const internals = _.internalsOf<NodeIteratorInternals>(this, 'NodeIterator', 'pointerBeforeReferenceNode')
const internals = _.internalsOf<NodeIteratorInternals>(
this,
'NodeIterator',
'pointerBeforeReferenceNode'
)
return internals.pointerBeforeReferenceNode
}
get referenceNode(): Node {
const internals = _.internalsOf<NodeIteratorInternals>(this, 'NodeIterator', 'referenceNode')
const internals = _.internalsOf<NodeIteratorInternals>(
this,
'NodeIterator',
'referenceNode'
)
return internals.referenceNode
}
get root(): Node {
const internals = _.internalsOf<NodeIteratorInternals>(this, 'NodeIterator', 'root')
const internals = _.internalsOf<NodeIteratorInternals>(
this,
'NodeIterator',
'root'
)
return internals.root
}
get whatToShow(): number {
const internals = _.internalsOf<NodeIteratorInternals>(this, 'NodeIterator', 'whatToShow')
const internals = _.internalsOf<NodeIteratorInternals>(
this,
'NodeIterator',
'whatToShow'
)
return internals.whatToShow
}
}

View file

@ -3,11 +3,12 @@ import * as _ from './utils'
export const hasOwn = {
hasOwn(instance: object, property: any) {
return _.__object_hasOwnProperty(instance, property)
}
},
}.hasOwn
export const initObject = (target: any, exclude: Set<string>) => {
if (exclude.has('Object') || exclude.has('object') || exclude.has('hasOwn')) return
if (exclude.has('Object') || exclude.has('object') || exclude.has('hasOwn'))
return
const Class = target.Object || globalThis.Object
@ -15,6 +16,6 @@ export const initObject = (target: any, exclude: Set<string>) => {
value: hasOwn,
writable: true,
enumerable: false,
configurable: true
configurable: true,
})
}

View file

@ -7,7 +7,10 @@ export class OffscreenCanvas extends EventTarget {
constructor(width: number, height: number) {
super()
if (arguments.length < 2) throw new TypeError(`Failed to construct 'OffscreenCanvas': 2 arguments required.`)
if (arguments.length < 2)
throw new TypeError(
`Failed to construct 'OffscreenCanvas': 2 arguments required.`
)
width = Number(width) || 0
height = Number(height) || 0
@ -31,8 +34,14 @@ export class OffscreenCanvas extends EventTarget {
_.internalsOf(this, 'OffscreenCanvas', 'width').width = Number(value) || 0
}
getContext(contextType: PredefinedContextId): CanvasRenderingContext2D | null {
const internals = _.internalsOf<OffscreenCanvasInternals>(this, 'HTMLCanvasElement', 'getContext')
getContext(
contextType: PredefinedContextId
): CanvasRenderingContext2D | null {
const internals = _.internalsOf<OffscreenCanvasInternals>(
this,
'HTMLCanvasElement',
'getContext'
)
switch (contextType) {
case '2d':
@ -54,15 +63,19 @@ export class OffscreenCanvas extends EventTarget {
void quality
return Promise.resolve(
new Blob([], { type })
)
return Promise.resolve(new Blob([], { type }))
}
}
_.allowStringTag(OffscreenCanvas)
const getImageType = (type: string): PredefinedImageType => type === 'image/avif' || type === 'image/jpeg' || type === 'image/png' || type === 'image/webp' ? type : 'image/png'
const getImageType = (type: string): PredefinedImageType =>
type === 'image/avif' ||
type === 'image/jpeg' ||
type === 'image/png' ||
type === 'image/webp'
? type
: 'image/png'
interface OffscreenCanvasInternals {
height: number
@ -75,6 +88,15 @@ interface ConvertToBlobOptions {
type: PredefinedImageType
}
type PredefinedContextId = '2d' | 'bitmaprenderer' | 'webgl' | 'webgl2' | 'webgpu'
type PredefinedContextId =
| '2d'
| 'bitmaprenderer'
| 'webgl'
| 'webgl2'
| 'webgpu'
type PredefinedImageType = 'image/avif' | 'image/jpeg' | 'image/png' | 'image/webp'
type PredefinedImageType =
| 'image/avif'
| 'image/jpeg'
| 'image/png'
| 'image/webp'

View file

@ -1,18 +1,16 @@
export const any = {
async any <T>(
iterable: Iterable<T | PromiseLike<T>>
): Promise<T> {
async any<T>(iterable: Iterable<T | PromiseLike<T>>): Promise<T> {
return Promise.all(
[...iterable].map(promise => {
[...iterable].map((promise) => {
return new Promise((resolve, reject) =>
Promise.resolve(promise).then(reject, resolve)
)
})
).then(
errors => Promise.reject(errors),
value => Promise.resolve<T>(value)
(errors) => Promise.reject(errors),
(value) => Promise.resolve<T>(value)
)
}
},
}.any
export const initPromise = (target: any, exclude: Set<string>) => {
@ -20,10 +18,11 @@ export const initPromise = (target: any, exclude: Set<string>) => {
const Class = target.Promise || globalThis.Promise
if (!Class.any) Object.defineProperty(Class, 'any', {
value: any,
writable: true,
enumerable: false,
configurable: true
})
if (!Class.any)
Object.defineProperty(Class, 'any', {
value: any,
writable: true,
enumerable: false,
configurable: true,
})
}

View file

@ -1,32 +1,50 @@
type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array
type TypedArray =
| Int8Array
| Uint8Array
| Uint8ClampedArray
| Int16Array
| Uint16Array
| Int32Array
| Uint32Array
| Float32Array
| Float64Array
| BigInt64Array
| BigUint64Array
export const at = {
at<T extends Array<any> | string | TypedArray>(this: T, index: number) {
index = Math.trunc(index) || 0
if (index < 0) index += this.length;
if (index < 0 || index >= this.length) return undefined;
return this[index];
}
if (index < 0) index += this.length
if (index < 0 || index >= this.length) return undefined
return this[index]
},
}.at
export const initRelativeIndexingMethod = (target: any, exclude: Set<string>) => {
export const initRelativeIndexingMethod = (
target: any,
exclude: Set<string>
) => {
if (exclude.has('at')) return
const Classes = []
if (!exclude.has('TypedArray')) Classes.push(Object.getPrototypeOf(target.Int8Array || globalThis.Int8Array))
if (!exclude.has('TypedArray'))
Classes.push(
Object.getPrototypeOf(target.Int8Array || globalThis.Int8Array)
)
if (!exclude.has('Array')) Classes.push(target.Array || globalThis.Array)
if (!exclude.has('String')) Classes.push(target.String || globalThis.String)
for (const Class of Classes) {
if (!Class.prototype.at) Object.defineProperty(Class.prototype, 'at', {
value: at,
writable: true,
enumerable: false,
configurable: true
})
if (!Class.prototype.at)
Object.defineProperty(Class.prototype, 'at', {
value: at,
writable: true,
enumerable: false,
configurable: true,
})
}
}

View file

@ -7,20 +7,35 @@ export class Storage {
getItem(key: string): string | null {
return getStringOrNull(
_.internalsOf<StorageInternals>(this, 'Storage', 'getItem').storage.get(String(key))
_.internalsOf<StorageInternals>(this, 'Storage', 'getItem').storage.get(
String(key)
)
)
}
key(index: number): string | null {
return getStringOrNull([ ..._.internalsOf<StorageInternals>(this, 'Storage', 'key').storage.keys() ][Number(index) || 0])
return getStringOrNull(
[
..._.internalsOf<StorageInternals>(
this,
'Storage',
'key'
).storage.keys(),
][Number(index) || 0]
)
}
removeItem(key: string): void {
_.internalsOf<StorageInternals>(this, 'Storage', 'getItem').storage.delete(String(key))
_.internalsOf<StorageInternals>(this, 'Storage', 'getItem').storage.delete(
String(key)
)
}
setItem(key: string, value: any): void {
_.internalsOf<StorageInternals>(this, 'Storage', 'getItem').storage.set(String(key), String(value))
_.internalsOf<StorageInternals>(this, 'Storage', 'getItem').storage.set(
String(key),
String(value)
)
}
get length() {
@ -28,7 +43,8 @@ export class Storage {
}
}
const getStringOrNull = (value: string | void) => typeof value === 'string' ? value : null
const getStringOrNull = (value: string | void) =>
typeof value === 'string' ? value : null
export const initStorage = (target: Target, exclude: Set<string>) => {
if (exclude.has('Storage') || exclude.has('localStorage')) return
@ -38,7 +54,7 @@ export const initStorage = (target: Target, exclude: Set<string>) => {
const storageInternals = new Map<string, string>()
_.INTERNALS.set(target.localStorage, {
storage: storageInternals
storage: storageInternals,
} as StorageInternals)
}

View file

@ -1,11 +1,18 @@
import * as _ from './utils'
export const replaceAll = {
replaceAll(this: string, searchValue: RegExp | string, replaceValue: string | ((substring: string, ...args: any[]) => string)) {
replaceAll(
this: string,
searchValue: RegExp | string,
replaceValue: string | ((substring: string, ...args: any[]) => string)
) {
return _.__object_isPrototypeOf(RegExp.prototype, searchValue)
? this.replace(searchValue as RegExp, replaceValue as string)
: this.replace(new RegExp(_.__string_escapeRegExp(searchValue as string), 'g'), replaceValue as string)
}
: this.replace(
new RegExp(_.__string_escapeRegExp(searchValue as string), 'g'),
replaceValue as string
)
},
}.replaceAll
export const initString = (target: any, exclude: Set<string>) => {
@ -13,10 +20,11 @@ export const initString = (target: any, exclude: Set<string>) => {
const Class = target.String || globalThis.String
if (!Class.prototype.replaceAll) Object.defineProperty(Class.prototype, 'replaceAll', {
value: replaceAll,
writable: true,
enumerable: false,
configurable: true
})
if (!Class.prototype.replaceAll)
Object.defineProperty(Class.prototype, 'replaceAll', {
value: replaceAll,
writable: true,
enumerable: false,
configurable: true,
})
}

View file

@ -1,9 +1,15 @@
import { setTimeout as nodeSetTimeout, clearTimeout as nodeClearTimeout } from 'node:timers'
import {
setTimeout as nodeSetTimeout,
clearTimeout as nodeClearTimeout,
} from 'node:timers'
import * as _ from './utils.js'
const INTERNAL = { tick: 0, pool: new Map }
const INTERNAL = { tick: 0, pool: new Map() }
export function setTimeout<TArgs extends any[], TFunc extends (...args: TArgs) => any>(callback: TFunc, delay = 0, ...args: TArgs): number {
export function setTimeout<
TArgs extends any[],
TFunc extends (...args: TArgs) => any
>(callback: TFunc, delay = 0, ...args: TArgs): number {
const func = _.__function_bind(callback, globalThis)
const tick = ++INTERNAL.tick
const timeout = nodeSetTimeout(func, delay, ...args)

View file

@ -30,17 +30,29 @@ export class TreeWalker {
}
get currentNode(): Node {
const internals = _.internalsOf<TreeWalkerInternals>(this, 'TreeWalker', 'currentNode')
const internals = _.internalsOf<TreeWalkerInternals>(
this,
'TreeWalker',
'currentNode'
)
return internals.currentNode
}
get root(): Node {
const internals = _.internalsOf<TreeWalkerInternals>(this, 'TreeWalker', 'root')
const internals = _.internalsOf<TreeWalkerInternals>(
this,
'TreeWalker',
'root'
)
return internals.root
}
get whatToShow(): number {
const internals = _.internalsOf<TreeWalkerInternals>(this, 'TreeWalker', 'whatToShow')
const internals = _.internalsOf<TreeWalkerInternals>(
this,
'TreeWalker',
'whatToShow'
)
return internals.whatToShow
}
}

View file

@ -1,74 +1,106 @@
import { default as nodeFetch, Headers, Request, Response } from 'node-fetch/src/index.js'
import {
default as nodeFetch,
Headers,
Request,
Response,
} from 'node-fetch/src/index.js'
import Stream from 'node:stream'
import * as _ from './utils'
export { Headers, Request, Response }
export const fetch = {
fetch(resource: string | URL | Request, init?: Partial<FetchInit>): Promise<Response> {
fetch(
resource: string | URL | Request,
init?: Partial<FetchInit>
): Promise<Response> {
const resourceURL = new URL(
_.__object_isPrototypeOf(Request.prototype, resource)
? (resource as Request).url
: _.pathToPosix(resource),
typeof Object(globalThis.process).cwd === 'function' ? 'file:' + _.pathToPosix(process.cwd()) + '/' : 'file:'
: _.pathToPosix(resource),
typeof Object(globalThis.process).cwd === 'function'
? 'file:' + _.pathToPosix(process.cwd()) + '/'
: 'file:'
)
if (resourceURL.protocol.toLowerCase() === 'file:') {
return import('node:fs').then(
fs => {
try {
const stats = fs.statSync(resourceURL)
const body = fs.createReadStream(resourceURL)
return import('node:fs').then((fs) => {
try {
const stats = fs.statSync(resourceURL)
const body = fs.createReadStream(resourceURL)
return new Response(
body,
{
status: 200,
statusText: '',
headers: {
'content-length': String(stats.size),
'date': new Date().toUTCString(),
'last-modified': new Date(stats.mtimeMs).toUTCString(),
}
}
)
} catch (error) {
const body = new Stream.Readable()
return new Response(body, {
status: 200,
statusText: '',
headers: {
'content-length': String(stats.size),
date: new Date().toUTCString(),
'last-modified': new Date(stats.mtimeMs).toUTCString(),
},
})
} catch (error) {
const body = new Stream.Readable()
body._read = () => {}
body.push(null)
body._read = () => {}
body.push(null)
return new Response(
body,
{
status: 404,
statusText: '',
headers: {
'date': new Date().toUTCString(),
}
}
)
}
return new Response(body, {
status: 404,
statusText: '',
headers: {
date: new Date().toUTCString(),
},
})
}
)
})
} else {
return nodeFetch(resource, init)
}
}
},
}.fetch
type USVString = ({} & string)
type USVString = {} & string
interface FetchInit {
body: Blob | BufferSource | FormData | URLSearchParams | ReadableStream | USVString
cache: 'default' | 'no-store' | 'reload' | 'no-cache' | 'force-cache' | 'only-if-cached'
body:
| Blob
| BufferSource
| FormData
| URLSearchParams
| ReadableStream
| USVString
cache:
| 'default'
| 'no-store'
| 'reload'
| 'no-cache'
| 'force-cache'
| 'only-if-cached'
credentials: 'omit' | 'same-origin' | 'include'
headers: Headers | Record<string, string>
method: 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'CONNECT' | 'OPTIONS' | 'TRACE' | 'PATCH' | USVString
method:
| 'GET'
| 'HEAD'
| 'POST'
| 'PUT'
| 'DELETE'
| 'CONNECT'
| 'OPTIONS'
| 'TRACE'
| 'PATCH'
| USVString
mode: 'cors' | 'no-cors' | 'same-origin' | USVString
redirect: 'follow' | 'manual' | 'error'
referrer: USVString
referrerPolicy: 'no-referrer' | 'no-referrer-when-downgrade' | 'same-origin' | 'origin' | 'strict-origin' | 'origin-when-cross-origin' | 'strict-origin-when-cross-origin' | 'unsafe-url'
referrerPolicy:
| 'no-referrer'
| 'no-referrer-when-downgrade'
| 'same-origin'
| 'origin'
| 'strict-origin'
| 'origin-when-cross-origin'
| 'strict-origin-when-cross-origin'
| 'unsafe-url'
integrity: USVString
keepalive: boolean
signal: AbortSignal

View file

@ -1,4 +1,4 @@
import { deserialize } from '@ungap/structured-clone/esm/deserialize.js';
import { serialize } from '@ungap/structured-clone/esm/serialize.js';
import { deserialize } from '@ungap/structured-clone/esm/deserialize.js'
import { serialize } from '@ungap/structured-clone/esm/serialize.js'
export default (any: any, options: any) => deserialize(serialize(any, options))

View file

@ -4,58 +4,93 @@ import { performance } from 'node:perf_hooks'
export const __date_now = Date.now
/** Returns the function bound to the given object. */
export const __function_bind = Function.bind.bind(Function.call as unknown as any) as <TArgs extends any[], TFunc extends (...args: TArgs) => any>(callback: TFunc, thisArg: unknown, ...args: TArgs) => TFunc
export const __function_bind = Function.bind.bind(
Function.call as unknown as any
) as <TArgs extends any[], TFunc extends (...args: TArgs) => any>(
callback: TFunc,
thisArg: unknown,
...args: TArgs
) => TFunc
/** Returns the function called with the specified values. */
export const __function_call = Function.call.bind(Function.call as unknown as any) as <TArgs extends any, TFunc extends (...args: TArgs[]) => any>(callback: TFunc, thisArg: unknown, ...args: TArgs[]) => ReturnType<TFunc>
export const __function_call = Function.call.bind(
Function.call as unknown as any
) as <TArgs extends any, TFunc extends (...args: TArgs[]) => any>(
callback: TFunc,
thisArg: unknown,
...args: TArgs[]
) => ReturnType<TFunc>
/** Returns an object with the specified prototype. */
export const __object_create = Object.create as { <T extends any = any>(value: T): any extends T ? Record<any, any> : T }
export const __object_create = Object.create as {
<T extends any = any>(value: T): any extends T ? Record<any, any> : T
}
/** Returns whether an object has a property with the specified name. */
export const __object_hasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty) as { <T1 extends object, T2>(object: T1, key: T2): T2 extends keyof T1 ? true : false }
export const __object_hasOwnProperty = Function.call.bind(
Object.prototype.hasOwnProperty
) as {
<T1 extends object, T2>(object: T1, key: T2): T2 extends keyof T1
? true
: false
}
/** Returns a string representation of an object. */
export const __object_toString = Function.call.bind(Object.prototype.toString) as { (value: any): string }
export const __object_toString = Function.call.bind(
Object.prototype.toString
) as { (value: any): string }
/** Returns whether the object prototype exists in another object. */
export const __object_isPrototypeOf = Function.call.bind(Object.prototype.isPrototypeOf) as { <T1 extends object, T2>(p: T1, v: T2): T2 extends T1 ? true : false }
export const __object_isPrototypeOf = Function.call.bind(
Object.prototype.isPrototypeOf
) as { <T1 extends object, T2>(p: T1, v: T2): T2 extends T1 ? true : false }
/** Current high resolution millisecond timestamp. */
export const __performance_now = performance.now as () => number
/** Returns the string escaped for use inside regular expressions. */
export const __string_escapeRegExp = (value: string) => value.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&')
export const __string_escapeRegExp = (value: string) =>
value.replace(/[\\^$*+?.()|[\]{}]/g, '\\$&')
// @ts-ignore
export const INTERNALS = new WeakMap<unknown, any>()
export const internalsOf = <T extends object>(target: T | object, className: string, propName: string): T => {
export const internalsOf = <T extends object>(
target: T | object,
className: string,
propName: string
): T => {
const internals: T = INTERNALS.get(target)
if (!internals) throw new TypeError(`${className}.${propName} can only be used on instances of ${className}`)
if (!internals)
throw new TypeError(
`${className}.${propName} can only be used on instances of ${className}`
)
return internals
}
export const allowStringTag = (value: any) => value.prototype[Symbol.toStringTag] = value.name
export const allowStringTag = (value: any) =>
(value.prototype[Symbol.toStringTag] = value.name)
/** Returns any kind of path as a posix path. */
export const pathToPosix = (pathname: any) => String(
pathname == null ? '' : pathname
).replace(
// convert slashes
/\\+/g, '/'
).replace(
// prefix a slash to drive letters
/^(?=[A-Za-z]:\/)/, '/'
).replace(
// encode path characters
/%/g, '%25'
).replace(
/\n/g, '%0A'
).replace(
/\r/g, '%0D'
).replace(
/\t/g, '%09'
)
export const pathToPosix = (pathname: any) =>
String(pathname == null ? '' : pathname)
.replace(
// convert slashes
/\\+/g,
'/'
)
.replace(
// prefix a slash to drive letters
/^(?=[A-Za-z]:\/)/,
'/'
)
.replace(
// encode path characters
/%/g,
'%25'
)
.replace(/\n/g, '%0A')
.replace(/\r/g, '%0D')
.replace(/\t/g, '%09')

View file

@ -60,7 +60,6 @@ import {
WritableStreamDefaultController,
WritableStreamDefaultWriter,
Window,
alert,
atob,
btoa,
@ -72,7 +71,6 @@ import {
requestIdleCallback,
setTimeout,
structuredClone,
initCustomElementRegistry,
initDocument,
initMediaQueryList,
@ -148,7 +146,6 @@ export {
WritableStreamDefaultController,
WritableStreamDefaultWriter,
Window,
alert,
atob,
btoa,
@ -245,18 +242,25 @@ export const polyfill = (target: any, options?: PolyfillOptions) => {
const excludeOptions = new Set(
typeof Object(options).exclude === 'string'
? String(Object(options).exclude).trim().split(/\s+/)
: Array.isArray(Object(options).exclude)
: Array.isArray(Object(options).exclude)
? Object(options).exclude.reduce(
(array: string[], entry: unknown) => array.splice(array.length, 0, ...(typeof entry === 'string' ? entry.trim().split(/\s+/) : [])) && array,
[]
)
: []
(array: string[], entry: unknown) =>
array.splice(
array.length,
0,
...(typeof entry === 'string' ? entry.trim().split(/\s+/) : [])
) && array,
[]
)
: []
) as Set<string>
// expand exclude options using exclusion shorthands
for (const excludeOption of excludeOptions) {
if (excludeOption in exclusions) {
for (const exclusion of exclusions[excludeOption as keyof typeof exclusions]) {
for (const exclusion of exclusions[
excludeOption as keyof typeof exclusions
]) {
excludeOptions.add(exclusion)
}
}
@ -267,11 +271,16 @@ export const polyfill = (target: any, options?: PolyfillOptions) => {
// skip WebAPIs that are excluded
if (excludeOptions.has(name)) continue
// skip WebAPIs that are built-in
// skip WebAPIs that are built-in
if (Object.hasOwnProperty.call(target, name)) continue
// define WebAPIs on the target
Object.defineProperty(target, name, { configurable: true, enumerable: true, writable: true, value: webAPIs[name as keyof typeof webAPIs] })
Object.defineProperty(target, name, {
configurable: true,
enumerable: true,
writable: true,
value: webAPIs[name as keyof typeof webAPIs],
})
}
// ensure WebAPIs correctly inherit other WebAPIs
@ -288,14 +297,17 @@ export const polyfill = (target: any, options?: PolyfillOptions) => {
// skip WebAPIs that are not available
if (!Class || !Super) continue
// skip WebAPIs that are already inherited correctly
// skip WebAPIs that are already inherited correctly
if (Object.getPrototypeOf(Class.prototype) === Super.prototype) continue
// define WebAPIs inheritence
Object.setPrototypeOf(Class.prototype, Super.prototype)
}
if (!excludeOptions.has('HTMLDocument') && !excludeOptions.has('HTMLElement')) {
if (
!excludeOptions.has('HTMLDocument') &&
!excludeOptions.has('HTMLElement')
) {
initDocument(target, excludeOptions)
if (!excludeOptions.has('CustomElementRegistry')) {

View file

@ -1,7 +1,13 @@
// @ts-check
import { AbortController, AbortSignal } from 'abort-controller/dist/abort-controller.mjs'
import { requestAnimationFrame, cancelAnimationFrame } from './lib/AnimationFrame'
import {
AbortController,
AbortSignal,
} from 'abort-controller/dist/abort-controller.mjs'
import {
requestAnimationFrame,
cancelAnimationFrame,
} from './lib/AnimationFrame'
import { atob, btoa } from './lib/Base64'
import { CharacterData, Comment, Text } from './lib/CharacterData'
import { File, Blob } from 'fetch-blob/from.js'
@ -12,22 +18,59 @@ import { cancelIdleCallback, requestIdleCallback } from './lib/IdleCallback'
import { Event, EventTarget } from 'event-target-shim'
import { fetch, Headers, Request, Response } from './lib/fetch'
import { FormData } from 'formdata-polyfill/esm.min.js'
import { ByteLengthQueuingStrategy, CountQueuingStrategy, ReadableByteStreamController, ReadableStream, ReadableStreamBYOBReader, ReadableStreamBYOBRequest, ReadableStreamDefaultController, ReadableStreamDefaultReader, TransformStream, WritableStream, WritableStreamDefaultController, WritableStreamDefaultWriter } from 'web-streams-polyfill/dist/ponyfill.es6.mjs'
import {
ByteLengthQueuingStrategy,
CountQueuingStrategy,
ReadableByteStreamController,
ReadableStream,
ReadableStreamBYOBReader,
ReadableStreamBYOBRequest,
ReadableStreamDefaultController,
ReadableStreamDefaultReader,
TransformStream,
WritableStream,
WritableStreamDefaultController,
WritableStreamDefaultWriter,
} from 'web-streams-polyfill/dist/ponyfill.es6.mjs'
import { URLPattern } from 'urlpattern-polyfill'
import { setTimeout, clearTimeout } from './lib/Timeout'
import structuredClone from './lib/structuredClone'
import { CanvasRenderingContext2D } from './lib/CanvasRenderingContext2D'
import { CSSStyleSheet, StyleSheet } from './lib/StyleSheet'
import { CustomElementRegistry, initCustomElementRegistry } from './lib/CustomElementRegistry'
import {
CustomElementRegistry,
initCustomElementRegistry,
} from './lib/CustomElementRegistry'
import { Document, HTMLDocument, initDocument } from './lib/Document'
import { DocumentFragment, Node, NodeFilter, NodeIterator, ShadowRoot } from './lib/Node'
import { Element, HTMLElement, HTMLBodyElement, HTMLDivElement, HTMLHeadElement, HTMLHtmlElement, HTMLSpanElement, HTMLStyleElement, HTMLTemplateElement, HTMLUnknownElement } from './lib/Element'
import {
DocumentFragment,
Node,
NodeFilter,
NodeIterator,
ShadowRoot,
} from './lib/Node'
import {
Element,
HTMLElement,
HTMLBodyElement,
HTMLDivElement,
HTMLHeadElement,
HTMLHtmlElement,
HTMLSpanElement,
HTMLStyleElement,
HTMLTemplateElement,
HTMLUnknownElement,
} from './lib/Element'
import { HTMLCanvasElement } from './lib/HTMLCanvasElement'
import { HTMLImageElement } from './lib/HTMLImageElement'
import { Image } from './lib/Image'
import { ImageData } from './lib/ImageData'
import { IntersectionObserver, MutationObserver, ResizeObserver } from './lib/Observer'
import {
IntersectionObserver,
MutationObserver,
ResizeObserver,
} from './lib/Observer'
import { MediaQueryList, initMediaQueryList } from './lib/MediaQueryList'
import { OffscreenCanvas } from './lib/OffscreenCanvas'
import { Storage, initStorage } from './lib/Storage'
@ -102,7 +145,6 @@ export {
WritableStreamDefaultController,
WritableStreamDefaultWriter,
Window,
alert,
atob,
btoa,
@ -114,7 +156,6 @@ export {
requestIdleCallback,
setTimeout,
structuredClone,
initCustomElementRegistry,
initDocument,
initMediaQueryList,

View file

@ -7,9 +7,9 @@ test(() => {
name: 'Supports Base64 Methods',
test() {
const target = {}
polyfill(target)
assert.equal('atob' in target, true)
assert.equal('btoa' in target, true)
assert.equal(typeof target['atob'], 'function')
@ -20,7 +20,7 @@ test(() => {
name: 'Supports atob(data)',
test() {
const target = {}
polyfill(target)
const a = 'SGVsbG8sIHdvcmxk'
@ -34,7 +34,7 @@ test(() => {
name: 'Supports btoa(data)',
test() {
const target = {}
polyfill(target)
const b = 'Hello, world'

View file

@ -8,8 +8,62 @@ test(() => {
{
name: 'Globals exist',
test() {
const webAPIs = [ 'AbortController', 'AbortSignal', 'Blob', 'ByteLengthQueuingStrategy', 'CSSStyleSheet', 'CountQueuingStrategy', 'CustomElementRegistry', 'CustomEvent', 'DOMException', 'Document', 'DocumentFragment', 'Element', 'Event', 'EventTarget', 'File', 'FormData', 'HTMLDocument', 'HTMLElement', 'HTMLDivElement', 'HTMLHeadElement', 'HTMLHtmlElement', 'HTMLImageElement', 'HTMLStyleElement', 'HTMLTemplateElement', 'HTMLUnknownElement', 'Headers', 'IntersectionObserver', 'Image', 'MediaQueryList', 'MutationObserver', 'Node', 'ReadableByteStreamController', 'ReadableStream', 'ReadableStreamBYOBReader', 'ReadableStreamBYOBRequest', 'ReadableStreamDefaultController', 'ReadableStreamDefaultReader', 'Request', 'Response', 'ShadowRoot', 'StyleSheet', 'TransformStream', 'WritableStream', 'WritableStreamDefaultController', 'WritableStreamDefaultWriter', 'Window', 'cancelAnimationFrame', 'cancelIdleCallback', 'clearTimeout', 'fetch', 'requestAnimationFrame', 'requestIdleCallback', 'setTimeout' ]
const webAPIs = [
'AbortController',
'AbortSignal',
'Blob',
'ByteLengthQueuingStrategy',
'CSSStyleSheet',
'CountQueuingStrategy',
'CustomElementRegistry',
'CustomEvent',
'DOMException',
'Document',
'DocumentFragment',
'Element',
'Event',
'EventTarget',
'File',
'FormData',
'HTMLDocument',
'HTMLElement',
'HTMLDivElement',
'HTMLHeadElement',
'HTMLHtmlElement',
'HTMLImageElement',
'HTMLStyleElement',
'HTMLTemplateElement',
'HTMLUnknownElement',
'Headers',
'IntersectionObserver',
'Image',
'MediaQueryList',
'MutationObserver',
'Node',
'ReadableByteStreamController',
'ReadableStream',
'ReadableStreamBYOBReader',
'ReadableStreamBYOBRequest',
'ReadableStreamDefaultController',
'ReadableStreamDefaultReader',
'Request',
'Response',
'ShadowRoot',
'StyleSheet',
'TransformStream',
'WritableStream',
'WritableStreamDefaultController',
'WritableStreamDefaultWriter',
'Window',
'cancelAnimationFrame',
'cancelIdleCallback',
'clearTimeout',
'fetch',
'requestAnimationFrame',
'requestIdleCallback',
'setTimeout',
]
for (const name of webAPIs) {
assert.equal(typeof globalThis[name], 'function')
}
@ -19,7 +73,7 @@ test(() => {
name: 'Constructs an Event',
test() {
const e = new Event('test')
assert.equal(e.type, 'test')
},
},
@ -33,17 +87,17 @@ test(() => {
name: 'Dispatches an Event on an EventTarget',
test() {
const t = new EventTarget()
let pass = false
t.addEventListener('test', (event) => {
pass = true
})
const e = new Event('test')
t.dispatchEvent(e)
assert.equal(pass, true)
},
},
@ -80,7 +134,7 @@ test(() => {
test() {
assert.equal(typeof String.prototype.at, 'function')
assert.equal(String.prototype.at.length, 1)
const example = 'The quick brown fox jumps over the lazy dog.'
assert.equal(example.at(2), 'e')
@ -92,7 +146,7 @@ test(() => {
test() {
assert.equal(typeof Array.prototype.at, 'function')
assert.equal(Array.prototype.at.length, 1)
const example = [1, 3, 5, 7, 9]
assert.equal(example.at(1), 3)
@ -104,7 +158,7 @@ test(() => {
test() {
assert.equal(typeof Int8Array.prototype.at, 'function')
assert.equal(Int8Array.prototype.at.length, 1)
const example = new Int8Array([1, 3, 5, 7, 9])
assert.equal(example.at(1), 3)
@ -120,7 +174,7 @@ test(() => {
const example = {}
assert.equal(Object.hasOwn(example, 'prop'), false)
example.prop = 'exists'
assert.equal(Object.hasOwn(example, 'prop'), true)
@ -132,11 +186,13 @@ test(() => {
assert.equal(typeof Promise.any, 'function')
assert.equal(Promise.any.length, 1)
Promise.any([Promise.resolve(42), Promise.reject(-1), Promise.reject(Infinity)]).then(
result => {
assert.equal(result, 42)
}
)
Promise.any([
Promise.resolve(42),
Promise.reject(-1),
Promise.reject(Infinity),
]).then((result) => {
assert.equal(result, 42)
})
},
},
{
@ -145,9 +201,11 @@ test(() => {
assert.equal(typeof String.prototype.replaceAll, 'function')
assert.equal(String.prototype.replaceAll.length, 2)
const t1 = 'Of all the sorcerers in Harry Potter, Halo is my favorite sorcerer.'
const t1 =
'Of all the sorcerers in Harry Potter, Halo is my favorite sorcerer.'
const t2 = t1.replaceAll('sorcerer', 'philosopher')
const t3 = 'Of all the philosophers in Harry Potter, Halo is my favorite philosopher.'
const t3 =
'Of all the philosophers in Harry Potter, Halo is my favorite philosopher.'
assert.equal(t2, t3)
},

View file

@ -33,7 +33,10 @@ test(() => {
})
assert.equal(new target.Comment().constructor.name, 'Comment')
assert.equal(Object.prototype.toString.call(new target.Comment()), '[object Comment]')
assert.equal(
Object.prototype.toString.call(new target.Comment()),
'[object Comment]'
)
assert.equal(new target.Comment('hello').data, 'hello')
assert.equal(new target.Comment('hello').textContent, 'hello')
@ -49,7 +52,10 @@ test(() => {
})
assert.equal(new target.Text().constructor.name, 'Text')
assert.equal(Object.prototype.toString.call(new target.Text()), '[object Text]')
assert.equal(
Object.prototype.toString.call(new target.Text()),
'[object Text]'
)
assert.equal(new target.Text('hello').data, 'hello')
assert.equal(new target.Text('hello').textContent, 'hello')

View file

@ -27,7 +27,10 @@ test(() => {
target.customElements.define('custom-element', CustomElement)
assert.equal(target.customElements.get('custom-element'), CustomElement)
assert.equal(target.customElements.getName(CustomElement), 'custom-element')
assert.equal(
target.customElements.getName(CustomElement),
'custom-element'
)
},
},
{
@ -40,13 +43,19 @@ test(() => {
assert.equal(target.document.body.localName, 'body')
assert.equal(target.document.body.tagName, 'BODY')
assert.equal(target.document.createElement('custom-element').constructor.name, 'HTMLUnknownElement')
assert.equal(
target.document.createElement('custom-element').constructor.name,
'HTMLUnknownElement'
)
const CustomElement = class HTMLCustomElement extends target.HTMLElement {}
target.customElements.define('custom-element', CustomElement)
assert.equal(target.document.createElement('custom-element').constructor.name, 'HTMLCustomElement')
assert.equal(
target.document.createElement('custom-element').constructor.name,
'HTMLCustomElement'
)
},
},
{

View file

@ -7,9 +7,9 @@ test(() => {
name: 'Fetch functionality',
test() {
const target = {}
polyfill(target)
assert.equal(Reflect.has(target, 'fetch'), true)
assert.equal(typeof target.fetch, 'function')
},
@ -18,7 +18,7 @@ test(() => {
name: 'Fetch with https',
async test() {
const target = {}
polyfill(target)
const { fetch } = target
@ -36,7 +36,7 @@ test(() => {
name: 'Fetch with file',
async test() {
const target = {}
polyfill(target)
const { fetch } = target
@ -62,7 +62,7 @@ test(() => {
name: 'Fetch with missing file',
async test() {
const target = {}
polyfill(target)
const { fetch } = target
@ -84,7 +84,7 @@ test(() => {
name: 'Fetch with (file) Request',
async test() {
const target = {}
polyfill(target)
const { Request, fetch } = target
@ -104,7 +104,7 @@ test(() => {
name: 'Fetch with relative file',
async test() {
const target = {}
polyfill(target)
const { fetch } = target
@ -120,14 +120,16 @@ test(() => {
name: 'Fetch with data',
async test() {
const target = {}
polyfill(target)
const { fetch } = target
const jsonURI = `data:application/json,${encodeURIComponent(JSON.stringify({
name: '@astrojs/webapi'
}))}`
const jsonURI = `data:application/json,${encodeURIComponent(
JSON.stringify({
name: '@astrojs/webapi',
})
)}`
const response = await fetch(jsonURI)

View file

@ -7,9 +7,9 @@ test(() => {
name: 'Supports ImageData',
test() {
const target = {}
polyfill(target)
assert.equal('ImageData' in target, true)
assert.equal(typeof target['ImageData'], 'function')
},
@ -18,7 +18,7 @@ test(() => {
name: 'Supports new (data: Uint8ClampedArray, width: number, height: number): ImageData',
test() {
const target = {}
polyfill(target)
const w = 640
@ -36,7 +36,7 @@ test(() => {
name: 'Supports new (data: Uint8ClampedArray, width: number): ImageData',
test() {
const target = {}
polyfill(target)
const w = 640
@ -54,7 +54,7 @@ test(() => {
name: 'Supports new (width: number, height: number): ImageData',
test() {
const target = {}
polyfill(target)
const w = 640
@ -71,7 +71,7 @@ test(() => {
name: 'Supports Object.keys(new ImageData(640, 480))',
test() {
const target = {}
polyfill(target)
const keys = Object.keys(new target.ImageData(640, 480))

View file

@ -7,7 +7,7 @@ test(() => {
name: 'Includes polyfill.internals functionality',
test() {
const target = {}
polyfill(target, { exclude: 'window document' })
const pseudo = { ...target }
@ -22,8 +22,13 @@ test(() => {
assert.equal(Reflect.has(pseudo, 'document'), true)
assert.equal(CustomElement.prototype.isPrototypeOf(pseudo.document.createElement('custom-element')), true)
assert.equal(
CustomElement.prototype.isPrototypeOf(
pseudo.document.createElement('custom-element')
),
true
)
},
}
},
]
})

View file

@ -7,9 +7,9 @@ test(() => {
name: 'Includes MediaQueryList functionality',
test() {
const target = {}
polyfill(target)
assert.equal(Reflect.has(target, 'MediaQueryList'), true)
assert.equal(Reflect.has(target, 'matchMedia'), true)
},
@ -18,7 +18,7 @@ test(() => {
name: 'Supports matchMedia creation',
test() {
const target = {}
polyfill(target)
const mql = target.matchMedia('(min-width: 640px)')

View file

@ -7,9 +7,9 @@ test(() => {
name: 'Supports OffscreenCanvas',
test() {
const target = {}
polyfill(target)
assert.equal('OffscreenCanvas' in target, true)
assert.equal(typeof target['OffscreenCanvas'], 'function')
},
@ -18,7 +18,7 @@ test(() => {
name: 'Supports new (width: number, height: number): OffscreenCanvas',
test() {
const target = {}
polyfill(target)
const w = 640
@ -34,7 +34,7 @@ test(() => {
name: 'Supports OffscreenCanvas#getContext',
test() {
const target = {}
polyfill(target)
const w = 640

View file

@ -7,11 +7,11 @@ test(() => {
name: 'Can exclude HTMLElement+',
test() {
const target = {}
polyfill(target, {
exclude: 'HTMLElement+'
exclude: 'HTMLElement+',
})
assert.equal(Reflect.has(target, 'Event'), true)
assert.equal(Reflect.has(target, 'EventTarget'), true)
assert.equal(Reflect.has(target, 'Element'), true)
@ -23,11 +23,11 @@ test(() => {
name: 'Can exclude Event+',
test() {
const target = {}
polyfill(target, {
exclude: 'Event+'
exclude: 'Event+',
})
assert.equal(Reflect.has(target, 'Event'), false)
assert.equal(Reflect.has(target, 'EventTarget'), false)
assert.equal(Reflect.has(target, 'Element'), false)
@ -39,11 +39,11 @@ test(() => {
name: 'Can exclude document',
test() {
const target = {}
polyfill(target, {
exclude: 'document'
exclude: 'document',
})
assert.equal(Reflect.has(target, 'Document'), true)
assert.equal(Reflect.has(target, 'HTMLDocument'), true)
assert.equal(Reflect.has(target, 'document'), false)

View file

@ -9,7 +9,7 @@ test(() => {
const target = {}
polyfill(target)
assert.equal(Reflect.has(target, 'Storage'), true)
assert.equal(Reflect.has(target, 'localStorage'), true)
assert.equal(typeof target.Storage, 'function')

View file

@ -9,7 +9,7 @@ test(() => {
const target = {}
polyfill(target)
assert.equal(Reflect.has(target, 'structuredClone'), true)
assert.equal(typeof target.structuredClone, 'function')
},
@ -22,9 +22,9 @@ test(() => {
polyfill(target)
const obj = {
foo: "bar",
foo: 'bar',
baz: {
qux: "quux",
qux: 'quux',
},
}

View file

@ -9,7 +9,7 @@ test(() => {
const target = {}
polyfill(target)
assert.equal(Reflect.has(target, 'URLPattern'), true)
assert.equal(typeof target.URLPattern, 'function')
},

View file

@ -12,4 +12,4 @@
"sourceMap": true,
"declarationMap": true
}
}
}