diff --git a/lib/jsdom/browser/Window.js b/lib/jsdom/browser/Window.js
index f769b926af..9b69142015 100644
--- a/lib/jsdom/browser/Window.js
+++ b/lib/jsdom/browser/Window.js
@@ -422,6 +422,19 @@ function Window(options) {
};
///// PUBLIC DATA PROPERTIES (TODO: should be getters)
+ this.customElements = new class CustomElementsRegistry {
+ get(tagName) {
+ return this[idlUtils.registry].get(tagName);
+ }
+
+ define(tagName, constructor) {
+ this[idlUtils.registry].set(tagName, constructor);
+ }
+
+ constructor() {
+ this[idlUtils.registry] = new Map();
+ }
+ };
this.console = {
assert: wrapConsoleMethod("assert"),
diff --git a/lib/jsdom/living/nodes/Document-impl.js b/lib/jsdom/living/nodes/Document-impl.js
index c0976c2fd7..fe1d682a1e 100644
--- a/lib/jsdom/living/nodes/Document-impl.js
+++ b/lib/jsdom/living/nodes/Document-impl.js
@@ -381,6 +381,11 @@ class DocumentImpl extends NodeImpl {
}
_createElementWithCorrectElementInterface(name, namespace) {
+ let Constructor = null;
+
+ if (Constructor = this._global.window.customElements.get(name)) {
+ return new Constructor();
+ }
// https://dom.spec.whatwg.org/#concept-element-interface
// TODO: eventually we should re-write the element-builder system to be namespace aware, but for now it is not.
const builder = this._elementBuilders[name.toLowerCase()] || this._defaultElementBuilder.bind(this);
diff --git a/lib/jsdom/living/nodes/HTMLElement-impl.js b/lib/jsdom/living/nodes/HTMLElement-impl.js
index 9838c1dbbd..2efa795230 100644
--- a/lib/jsdom/living/nodes/HTMLElement-impl.js
+++ b/lib/jsdom/living/nodes/HTMLElement-impl.js
@@ -13,6 +13,7 @@ class HTMLElementImpl extends ElementImpl {
constructor(args, privateData) {
super(args, privateData);
this._initGlobalEvents();
+ this._core = this._core || global.window;
this._tabIndex = 0;
diff --git a/package.json b/package.json
index f6a45efeaf..f4b1733b5f 100644
--- a/package.json
+++ b/package.json
@@ -66,7 +66,7 @@
"st": "^1.2.0",
"watchify": "^3.9.0",
"wd": "^1.1.3",
- "webidl2js": "^7.0.1"
+ "webidl2js": "jsdom/webidl2js#1868f38611e7d9b6e598036de129100bf5e98b6c"
},
"browser": {
"canvas": false,
diff --git a/test-web-components.js b/test-web-components.js
new file mode 100644
index 0000000000..d1fb0fe4cc
--- /dev/null
+++ b/test-web-components.js
@@ -0,0 +1,46 @@
+// Modified JSDOM to allow `super` on `HTMLElement`.
+const { JSDOM } = require('./');
+const { window } = new JSDOM('')
+
+// FIXME Necessary for now to get MyShinyComponent in the shared JSDOM window.
+global.window = window;
+
+// Web Components on the way...!
+const { HTMLElement, document, customElements } = window;
+
+// Plain ole Custom Element...
+class MyShinyComponent extends HTMLElement {
+ constructor(props = { someMessage: 'Set via innerHTML' }) {
+ super();
+
+ this.innerHTML = `${props.someMessage}`;
+ }
+}
+
+// Define into the internal JSDOM CustomElementsRegistry
+customElements.define('my-shiny-component', MyShinyComponent);
+
+// Helper function to create a regular DOM Node or upgraded Custom Element.
+function makeElement(tagName, props) {
+ const Constructor = customElements.get(tagName);
+
+ if (Constructor) {
+ return new Constructor(props);
+ }
+ else {
+ document.createElement(tagName);
+ }
+}
+
+//console.log(
+// makeElement('my-shiny-component', { someMessage: 'Hello World' }).outerHTML
+//);
+
+document.body.innerHTML = '';
+
+/**
+ *
+ *
+ * @return
+ */
+console.log(document.body.outerHTML);