UNPKG

@webcomponents/custom-elements

Version:
55 lines (45 loc) 2 kB
import Native from './Native.js'; import CustomElementInternals from '../CustomElementInternals.js'; import CEState from '../CustomElementState.js'; import AlreadyConstructedMarker from '../AlreadyConstructedMarker.js'; /** * @param {!CustomElementInternals} internals */ export default function(internals) { window['HTMLElement'] = (function() { /** * @type {function(new: HTMLElement): !HTMLElement} */ function HTMLElement() { // This should really be `new.target` but `new.target` can't be emulated // in ES5. Assuming the user keeps the default value of the constructor's // prototype's `constructor` property, this is equivalent. /** @type {!Function} */ const constructor = this.constructor; const definition = internals.constructorToDefinition(constructor); if (!definition) { throw new Error('The custom element being constructed was not registered with `customElements`.'); } const constructionStack = definition.constructionStack; if (constructionStack.length === 0) { const element = Native.Document_createElement.call(document, definition.localName); Object.setPrototypeOf(element, constructor.prototype); element.__CE_state = CEState.custom; element.__CE_definition = definition; internals.patch(element); return element; } const lastIndex = constructionStack.length - 1; const element = constructionStack[lastIndex]; if (element === AlreadyConstructedMarker) { throw new Error('The HTMLElement constructor was either called reentrantly for this constructor or called multiple times.'); } constructionStack[lastIndex] = AlreadyConstructedMarker; Object.setPrototypeOf(element, constructor.prototype); internals.patch(/** @type {!HTMLElement} */ (element)); return element; } HTMLElement.prototype = Native.HTMLElement.prototype; return HTMLElement; })(); };