All files / _.ts

100.00% Branches 3/3
100.00% Lines 70/70
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
x1
x1
 
 
x10
x10
 
x10
x10
 
x10
x10
x3871
x3884
x3884
x3871
 
x10
x10
x162
x10
x10
x64
x64
x10
 
x10
x10
x12
x12
x12
x12
x12
 
x10
x10
x10
x10
x639
x639
x639
 
x20
x14
x14
 
x10
x34
x34
x34
x34
x34
x34
x34
x34
x34
x34
x34
x34
x10
x10
x10
x10
x10
x10
x10
x10
x10
x10
x10
x10
x10
x10
x10
x10
x10
x10
x10
x10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

































































































/// <reference lib="dom" />
// Imports
import type { record, rw } from "@libs/typing"

/** Implementation version */
export const version = "0.0"

/** Pass as argument to allow instantiation of illegal constructors. */
export const internal: unique symbol = Symbol.for("@@internal")

/** Throws if {@link internal} symbol is not present in arguments. */
export function illegal(args: IArguments): void {
  if ((!args[0]) || (typeof args[0] !== "object") || (!(internal in args[0]))) {
    throw new TypeError("Illegal constructor")
  }
}

/** Throws a "NotSupportedError" DOMException when something is not implemented. */
export const unimplemented = Object.assign(function (): never {
  throw new DOMException("While this feature is supposed to be supported, it has not been implemented yet in @libs/dom", "NotSupportedError")
}, {
  getter<T>() {
    return unimplemented()
  },
})

/** Dispatch event to listeners and to shorthand property */
export function dispatch<T extends EventTarget>(element: T, event: Event) {
  element.dispatchEvent(event)
  if (`on${event.type}` in element) {
    ;(element as rw)[`on${event.type}`]?.(event)
  }
}

/** Indexable is an array-like class that makes the object indexable without implementing Array.prototype. */
export class Indexable<T> extends Array<T> implements ArrayLike<T> {
  // deno-lint-ignore no-explicit-any
  constructor(..._: any[]) {
    super()
    illegal(arguments)
  }

  get [Symbol.toStringTag](): string {
    return this.constructor.name
  }

  get [internal](): Pick<Array<T>, "push" | "pop" | "find" | "shift" | "unshift" | "splice" | "indexOf" | "map" | "filter"> {
    return {
      push: super.push.bind(this),
      pop: super.pop.bind(this),
      shift: super.shift.bind(this),
      unshift: super.unshift.bind(this),
      splice: super.splice.bind(this),
      indexOf: super.indexOf.bind(this),
      find: super.find.bind(this),
      map: super.map.bind(this),
      filter: super.filter.bind(this),
    }
  }
}
new Set(Object.getOwnPropertyNames(Array)).difference(
  new Set([
    "prototype",
    "name",
    "length",
  ]),
).forEach((property) => (Indexable as unknown as record)[property] = undefined)
new Set(Object.getOwnPropertyNames(Array.prototype)).difference(
  new Set([
    "constructor",
    "item",
    "keys",
    "values",
    "entries",
    "forEach",
    "length",
    "toString",
  ]),
).forEach((property) => (Indexable.prototype as unknown as record)[property] = undefined)

// DOM re-exports

export type _Permissions = Permissions
export type _PermissionsStatus = PermissionStatus
export type _UserActivation = UserActivation
export type _Navigator = Navigator
export type _MimeTypeArray = MimeTypeArray
export type _MimeType = MimeType
export type _Clipboard = Clipboard
export type _ClipboardItem = ClipboardItem
export type _ClipboardEvent = ClipboardEvent

export type _Node = Node
export type _NodeList = NodeList
export type _Document = Document
export type _DocumentFragment = DocumentFragment
export type _Element = Element
export type _Window = Window
export type _BarProp = BarProp
export type _Attr = Attr