Skip to content

Instantly share code, notes, and snippets.

@jridgewell
Last active April 30, 2020 22:03
Show Gist options
  • Select an option

  • Save jridgewell/9554bc2ae3e2234ba0b2e0bd11fc755f to your computer and use it in GitHub Desktop.

Select an option

Save jridgewell/9554bc2ae3e2234ba0b2e0bd11fc755f to your computer and use it in GitHub Desktop.
Subclassing custom elements (https://jsbench.github.io/#9554bc2ae3e2234ba0b2e0bd11fc755f) #jsbench #jsperf
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Subclassing custom elements</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/1.0.0/benchmark.min.js"></script>
<style>
body {
font-size: 20px;
}
</style>
</head>
<body>
<h1>Open the console to view the results</h1>
<h2><code>cmd + alt + j</code> or <code>ctrl + alt + j</code></h2>
<script src="./suite.js"></script>
</body>
</html>
"use strict";
(function (factory) {
if (typeof Benchmark !== "undefined") {
factory(Benchmark);
} else {
factory(require("benchmark"));
}
})(function (Benchmark) {
var suite = new Benchmark.Suite();
// Benchmark.prototype.setup = function () {
if (!customElements.get("x-call-local")) {
const HTMLElement = window.HTMLElement;
const cache = Object.create(null);
function WrappedHTMLElement(name) {
return (
// cache[name] ||
(/*cache[name] =*/ Reflect.construct(HTMLElement, [], this.constructor))
);
}
Object.setPrototypeOf(WrappedHTMLElement, HTMLElement);
Object.setPrototypeOf(
WrappedHTMLElement.prototype,
HTMLElement.prototype
);
window.HTMLElement = WrappedHTMLElement;
function BaseCustomElementLocalName(name) {
const _this = WrappedHTMLElement.call(this, name) || this;
_this.createdCallback();
return _this;
}
BaseCustomElementLocalName.prototype.createdCallback = function () {
this.x = this.localName;
};
Object.setPrototypeOf(BaseCustomElementLocalName, WrappedHTMLElement);
Object.setPrototypeOf(
BaseCustomElementLocalName.prototype,
WrappedHTMLElement.prototype
);
window.CustomElementWithCallLocalName = function CustomElementWithCallLocalName(
name
) {
return BaseCustomElementLocalName.call(this, name) || this;
};
Object.setPrototypeOf(
CustomElementWithCallLocalName,
BaseCustomElementLocalName
);
Object.setPrototypeOf(
CustomElementWithCallLocalName.prototype,
BaseCustomElementLocalName.prototype
);
window.CustomElementWithApplyLocalName = function CustomElementWithApplyLocalName() {
return BaseCustomElementLocalName.apply(this, arguments) || this;
};
Object.setPrototypeOf(
CustomElementWithApplyLocalName,
BaseCustomElementLocalName
);
Object.setPrototypeOf(
CustomElementWithApplyLocalName.prototype,
BaseCustomElementLocalName.prototype
);
function BaseCustomElementElementName(name) {
const _this = WrappedHTMLElement.call(this, name) || this;
_this.createdCallback();
return _this;
}
BaseCustomElementElementName.prototype.createdCallback = function () {
this.x = this.elementName();
};
Object.setPrototypeOf(BaseCustomElementElementName, WrappedHTMLElement);
Object.setPrototypeOf(
BaseCustomElementElementName.prototype,
WrappedHTMLElement.prototype
);
window.CustomElementWithCallElementName = function CustomElementWithCallElementName(
name
) {
return BaseCustomElementElementName.call(this, name) || this;
};
CustomElementWithCallElementName.prototype.elementName = function () {
return "x-call-element";
};
Object.setPrototypeOf(
CustomElementWithCallElementName,
BaseCustomElementElementName
);
Object.setPrototypeOf(
CustomElementWithCallElementName.prototype,
BaseCustomElementElementName.prototype
);
window.CustomElementWithApplyElementName = function CustomElementWithApplyElementName() {
return BaseCustomElementElementName.apply(this, arguments) || this;
};
CustomElementWithApplyElementName.prototype.elementName = function () {
return "x-apply-element";
};
Object.setPrototypeOf(
CustomElementWithApplyElementName,
BaseCustomElementElementName
);
Object.setPrototypeOf(
CustomElementWithApplyElementName.prototype,
BaseCustomElementElementName.prototype
);
customElements.define("x-call-local", CustomElementWithCallLocalName);
customElements.define("x-apply-local", CustomElementWithApplyLocalName);
customElements.define("x-call-element", CustomElementWithCallElementName);
customElements.define(
"x-apply-element",
CustomElementWithApplyElementName
);
}
// };
const suites = [
[
"new CustomElementWithCallLocalName();",
function () {
new CustomElementWithCallLocalName("x-call-local");
// document.createElement('x-call-local');
},
],
[
"new CustomElementWithCallElementName();",
function () {
new CustomElementWithCallElementName("x-call-element");
// document.createElement('x-call-element');
},
],
[
"new CustomElementWithApplyLocalName();",
function () {
new CustomElementWithApplyLocalName("x-apply-local");
// document.createElement('x-apply-local');
},
],
[
"new CustomElementWithApplyElementName();",
function () {
new CustomElementWithApplyElementName("x-apply-element");
// document.createElement('x-apply-element');
},
],
];
function shuffle(array) {
const length = array == null ? 0 : array.length;
if (!length) {
return [];
}
let index = -1;
const lastIndex = length - 1;
const result = array.slice();
while (++index < length) {
const rand = index + Math.floor(Math.random() * (lastIndex - index + 1));
const value = result[rand];
result[rand] = result[index];
result[index] = value;
}
return result;
}
shuffle(suites).forEach(function (s) {
suite.add(s[0], s[1]);
});
for (let i = 0; i < 1000; i++) {
shuffle(suites).forEach(function (s) {
s[1]();
});
}
suite.on("cycle", function (evt) {
console.log(" - " + evt.target);
});
suite.on("complete", function (evt) {
console.log(new Array(30).join("-"));
var results = evt.currentTarget.sort(function (a, b) {
return b.hz - a.hz;
});
results = results.map(function (item, idx) {
return idx + 1 + ". " + item;
});
document.body.innerHTML = `<pre>${results.join("\n")}`;
});
console.log("Subclassing custom elements");
console.log(new Array(30).join("-"));
suite.run();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment