Skip to content

Commit 8982a21

Browse files
committed
1 parent 0470cf7 commit 8982a21

File tree

1 file changed

+112
-45
lines changed

1 file changed

+112
-45
lines changed

src/lib/polyfill.js

Lines changed: 112 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,63 @@
1+
// polyfill for Object.hasOwn
2+
3+
(function () {
4+
var oldHasOwn = Function.prototype.call.bind(
5+
Object.prototype.hasOwnProperty,
6+
);
7+
if (oldHasOwn(Object, "hasOwn")) return;
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")) {
6-
return;
7-
}
23+
if (Object.hasOwn(item, "prepend")) return;
824
Object.defineProperty(item, "prepend", {
925
configurable: true,
10-
enumerable: true,
26+
enumerable: false,
1127
writable: true,
1228
value: function prepend() {
13-
var argArr = Array.prototype.slice.call(arguments),
14-
docFrag = document.createDocumentFragment();
29+
var docFrag = document.createDocumentFragment();
1530

16-
argArr.forEach(function (argItem) {
17-
var node =
31+
var argLength = arguments.length;
32+
for (var i = 0; i < argLength; i++) {
33+
var argItem = arguments[i];
34+
docFrag.appendChild(
1835
argItem instanceof Node
1936
? argItem
20-
: document.createTextNode(String(argItem));
21-
docFrag.appendChild(node);
22-
});
37+
: document.createTextNode(argItem),
38+
);
39+
}
2340

2441
this.insertBefore(docFrag, this.firstChild);
2542
},
2643
});
44+
item.prepend.prototype = null;
2745
});
2846
})([Element.prototype, Document.prototype, DocumentFragment.prototype]);
2947

3048
// polyfill for closest
3149

3250
(function (arr) {
3351
arr.forEach(function (item) {
34-
if (item.hasOwnProperty("closest")) {
35-
return;
36-
}
52+
if (Object.hasOwn(item, "closest")) return;
3753
Object.defineProperty(item, "closest", {
3854
configurable: true,
39-
enumerable: true,
55+
enumerable: false,
4056
writable: true,
4157
value: function closest(s) {
42-
var matches = (this.document || this.ownerDocument).querySelectorAll(s),
58+
var matches = (this.document || this.ownerDocument).querySelectorAll(
59+
s,
60+
),
4361
i,
4462
el = this;
4563
do {
@@ -49,68 +67,89 @@
4967
return el;
5068
},
5169
});
70+
item.closest.prototype = null;
5271
});
5372
})([Element.prototype]);
5473

5574
// polyfill for replaceWith
5675

5776
(function (arr) {
5877
arr.forEach(function (item) {
59-
if (item.hasOwnProperty("replaceWith")) {
60-
return;
61-
}
78+
var className = item.name;
79+
item = item.prototype;
80+
if (Object.hasOwn(item, "replaceWith")) return;
6281
Object.defineProperty(item, "replaceWith", {
6382
configurable: true,
64-
enumerable: true,
83+
enumerable: false,
6584
writable: true,
6685
value: function replaceWith() {
67-
var parent = this.parentNode,
68-
i = arguments.length,
69-
currentNode;
86+
var parent = this.parentNode;
7087
if (!parent) return;
71-
if (!i)
72-
// if there are no arguments
73-
parent.removeChild(this);
74-
while (i--) {
75-
// i-- decrements i and returns the value of i before the decrement
76-
currentNode = arguments[i];
77-
if (typeof currentNode !== "object") {
78-
currentNode = this.ownerDocument.createTextNode(currentNode);
79-
} else if (currentNode.parentNode) {
80-
currentNode.parentNode.removeChild(currentNode);
88+
var viableNextSibling = this.nextSibling;
89+
var argLength = arguments.length;
90+
while (viableNextSibling) {
91+
var inArgs = false;
92+
for (var j = 0; j < argLength; j++) {
93+
if (arguments[j] === viableNextSibling) {
94+
inArgs = true;
95+
break;
96+
}
97+
}
98+
if (!inArgs) break;
99+
viableNextSibling = viableNextSibling.nextSibling;
100+
}
101+
this.remove();
102+
var docFrag = document.createDocumentFragment();
103+
try {
104+
for (var i = 0; i < argLength; i++) {
105+
var currentNode = arguments[i];
106+
if (currentNode instanceof Node) {
107+
var parent2 = currentNode;
108+
do {
109+
if (parent2 !== parent) continue;
110+
throw new DOMException(
111+
"Failed to execute 'replaceWith' on '" +
112+
className +
113+
"': The new child element contains the parent.",
114+
);
115+
} while ((parent2 = parent2.parentNode));
116+
} else {
117+
currentNode = this.ownerDocument.createTextNode(currentNode);
118+
}
119+
docFrag.appendChild(currentNode);
120+
}
121+
} finally {
122+
if (argLength >= 1) {
123+
parent.insertBefore(docFrag, viableNextSibling);
81124
}
82-
// the value of "i" below is after the decrement
83-
if (!i)
84-
// if currentNode is the first argument (currentNode === arguments[0])
85-
parent.replaceChild(currentNode, this);
86-
// if currentNode isn't the first
87-
else parent.insertBefore(this.previousSibling, currentNode);
88125
}
89126
},
90127
});
128+
item.replaceWith.prototype = null;
91129
});
92-
})([Element.prototype, CharacterData.prototype, DocumentType.prototype]);
130+
})([Element, CharacterData, DocumentType]);
93131

94132
// polyfill for toggleAttribute
95133

96134
(function (arr) {
97135
arr.forEach(function (item) {
98-
if (item.hasOwnProperty("toggleAttribute")) {
99-
return;
100-
}
136+
if (Object.hasOwn(item, "toggleAttribute")) return;
101137
Object.defineProperty(item, "toggleAttribute", {
102138
configurable: true,
103-
enumerable: true,
139+
enumerable: false,
104140
writable: true,
105141
value: function toggleAttribute() {
106142
var attr = arguments[0];
107143
if (this.hasAttribute(attr)) {
108144
this.removeAttribute(attr);
145+
return false;
109146
} else {
110-
this.setAttribute(attr, arguments[1] || "");
147+
this.setAttribute(attr, arguments.length >= 2 ? arguments[1] : "");
148+
return true;
111149
}
112150
},
113151
});
152+
item.toggleAttribute.prototype = null;
114153
});
115154
})([Element.prototype]);
116155

@@ -140,3 +179,31 @@
140179
};
141180
}
142181
})();
182+
183+
// polyfill for Promise.withResolvers
184+
185+
if (!Object.hasOwn(Promise, "withResolvers")) {
186+
Object.defineProperty(Promise, "withResolvers", {
187+
configurable: true,
188+
enumerable: false,
189+
writable: true,
190+
value: function withResolvers() {
191+
var resolve, reject;
192+
var promise = new this(function (_resolve, _reject) {
193+
resolve = _resolve;
194+
reject = _reject;
195+
});
196+
if (typeof resolve !== "function" || typeof reject !== "function") {
197+
throw new TypeError(
198+
"Promise resolve or reject function is not callable",
199+
);
200+
}
201+
return {
202+
promise: promise,
203+
resolve: resolve,
204+
reject: reject,
205+
};
206+
},
207+
});
208+
Promise.withResolvers.prototype = null;
209+
}

0 commit comments

Comments
 (0)