Skip to content

Commit f00e795

Browse files
committed
feat: Add more polyfills and refactor some
1 parent 0470cf7 commit f00e795

File tree

1 file changed

+93
-20
lines changed

1 file changed

+93
-20
lines changed

src/lib/polyfill.js

Lines changed: 93 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,63 @@
1+
// polyfill for Object.hasOwn
2+
3+
(function () {
4+
var oldHasOwn = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
5+
if (oldHasOwn(Object, "hasOwn")) {
6+
return;
7+
}
8+
Object.defineProperty(Object, "hasOwn", {
9+
configurable: true,
10+
enumerable: false,
11+
writable: true,
12+
value: function hasOwn(obj, prop) {
13+
return oldHasOwn(obj, prop);
14+
},
15+
});
16+
Object.hasOwn.prototype = null;
17+
})();
18+
119
// polyfill for prepend
220

321
(function (arr) {
422
arr.forEach(function (item) {
5-
if (item.hasOwnProperty("prepend")) {
23+
if (Object.hasOwn(item, "prepend")) {
624
return;
725
}
826
Object.defineProperty(item, "prepend", {
927
configurable: true,
10-
enumerable: true,
28+
enumerable: false,
1129
writable: true,
1230
value: function prepend() {
13-
var argArr = Array.prototype.slice.call(arguments),
14-
docFrag = document.createDocumentFragment();
15-
16-
argArr.forEach(function (argItem) {
17-
var node =
18-
argItem instanceof Node
19-
? argItem
20-
: document.createTextNode(String(argItem));
21-
docFrag.appendChild(node);
22-
});
31+
var docFrag = createDocumentFragment();
32+
33+
var i = 0,
34+
argItem,
35+
length = arguments.length;
36+
while (i < length) {
37+
argItem = arguments[i++];
38+
if (!(argItem instanceof Node)) {
39+
argItem += ""
40+
}
41+
docFrag.appendChild(createTextNode(argItem));
42+
}
2343

2444
this.insertBefore(docFrag, this.firstChild);
2545
},
2646
});
47+
item.prepend.prototype = null;
2748
});
2849
})([Element.prototype, Document.prototype, DocumentFragment.prototype]);
2950

3051
// polyfill for closest
3152

3253
(function (arr) {
3354
arr.forEach(function (item) {
34-
if (item.hasOwnProperty("closest")) {
55+
if (Object.hasOwn(item, "closest")) {
3556
return;
3657
}
3758
Object.defineProperty(item, "closest", {
3859
configurable: true,
39-
enumerable: true,
60+
enumerable: false,
4061
writable: true,
4162
value: function closest(s) {
4263
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
@@ -49,19 +70,20 @@
4970
return el;
5071
},
5172
});
73+
item.closest.prototype = null;
5274
});
5375
})([Element.prototype]);
5476

5577
// polyfill for replaceWith
5678

5779
(function (arr) {
5880
arr.forEach(function (item) {
59-
if (item.hasOwnProperty("replaceWith")) {
81+
if (Object.hasOwn(item, "replaceWith")) {
6082
return;
6183
}
6284
Object.defineProperty(item, "replaceWith", {
6385
configurable: true,
64-
enumerable: true,
86+
enumerable: false,
6587
writable: true,
6688
value: function replaceWith() {
6789
var parent = this.parentNode,
@@ -75,7 +97,7 @@
7597
// i-- decrements i and returns the value of i before the decrement
7698
currentNode = arguments[i];
7799
if (typeof currentNode !== "object") {
78-
currentNode = this.ownerDocument.createTextNode(currentNode);
100+
currentNode = createTextNode(currentNode, this.ownerDocument);
79101
} else if (currentNode.parentNode) {
80102
currentNode.parentNode.removeChild(currentNode);
81103
}
@@ -88,29 +110,31 @@
88110
}
89111
},
90112
});
113+
item.replaceWith.prototype = null;
91114
});
92115
})([Element.prototype, CharacterData.prototype, DocumentType.prototype]);
93116

94117
// polyfill for toggleAttribute
95118

96119
(function (arr) {
97120
arr.forEach(function (item) {
98-
if (item.hasOwnProperty("toggleAttribute")) {
121+
if (Object.hasOwn(item, "toggleAttribute")) {
99122
return;
100123
}
101124
Object.defineProperty(item, "toggleAttribute", {
102125
configurable: true,
103-
enumerable: true,
126+
enumerable: false,
104127
writable: true,
105128
value: function toggleAttribute() {
106129
var attr = arguments[0];
107130
if (this.hasAttribute(attr)) {
108131
this.removeAttribute(attr);
109132
} else {
110-
this.setAttribute(attr, arguments[1] || "");
133+
this.setAttribute(attr, arguments.length >= 2 ? arguments[1] : "");
111134
}
112135
},
113136
});
137+
item.toggleAttribute.prototype = null;
114138
});
115139
})([Element.prototype]);
116140

@@ -140,3 +164,52 @@
140164
};
141165
}
142166
})();
167+
168+
// polyfill for Promise.withResolvers
169+
170+
if (!Object.hasOwn(Promise, "withResolvers")) {
171+
(function () {
172+
Object.defineProperty(Promise, "withResolvers", {
173+
configurable: true,
174+
enumerable: false,
175+
writable: true,
176+
value: function withResolvers() {
177+
var resolve, reject;
178+
var promise = new this(function (_resolve, _reject) {
179+
resolve = _resolve;
180+
reject = _reject;
181+
});
182+
if (typeof resolve !== "function" || typeof reject !== "function") {
183+
throw new TypeError(
184+
"Promise resolve or reject function is not callable",
185+
);
186+
}
187+
return {
188+
promise: promise,
189+
resolve: resolve,
190+
reject: reject,
191+
};
192+
},
193+
});
194+
Promise.withResolvers.prototype = null;
195+
})();
196+
}
197+
198+
// utils
199+
200+
function createTextNode(text, doc) {
201+
if (doc === undefined) doc = document;
202+
try {
203+
if (doc !== document) throw 0;
204+
return new Text(text);
205+
} catch {
206+
return doc.createTextNode(text);
207+
}
208+
}
209+
function createDocumentFragment() {
210+
try {
211+
return new DocumentFragment();
212+
} catch {
213+
return document.createDocumentFragment();
214+
}
215+
}

0 commit comments

Comments
 (0)