added custom element functions

This commit is contained in:
hariroshan 2023-01-05 15:59:22 +05:30
parent ff471954dc
commit 803e46f78a
9 changed files with 995 additions and 2 deletions

4
.gitignore vendored
View File

@ -29,3 +29,7 @@ typings/
# Rescript
lib
*.bs.js
# Elm
elm-stuff

View File

@ -13,5 +13,6 @@
}
],
"suffix": ".bs.js",
"bsc-flags": [],
"bs-dependencies": []
}

View File

@ -13,7 +13,9 @@
"dependencies": {
"@nativescript/core": "~8.4.0",
"@nativescript/theme": "~3.0.2",
"elm": "^0.19.1-5"
"elm": "^0.19.1-5",
"happy-dom": "^8.1.2",
"vm-shim": "^0.0.6"
},
"devDependencies": {
"@nativescript/types": "~8.4.0",

149
src/CustomElement.res Normal file
View File

@ -0,0 +1,149 @@
type constructor = {
observedAttributes: array<string>,
name: string,
}
type event
type nativeObject = {
on: (event, event => unit) => unit,
off: (event, event => unit) => unit,
}
type super = {
addEventListener: (event, event => unit) => unit,
removeEventListener: (event, event => unit) => unit,
}
type extendedThis = {
getAttributes: unit => Js.Dict.t<string>,
getProps: unit => Js.Dict.t<string>,
init: unit => unit,
update: (string, string) => unit,
dispose: unit => unit,
isConnected: bool,
render: Js.Nullable.t<unit => unit>,
object: nativeObject,
}
type this = {
getAttribute: string => Js.Nullable.t<string>,
style: string,
super: super,
constructor: constructor,
}
%%private(
@scope("prototype") @set
external assignGetPropsInProto: (Obj.t, unit => Js.Dict.t<string>) => unit = "getProps"
@scope("prototype") @set
external assignGetAttributes: (Obj.t, unit => Js.Dict.t<string>) => unit = "getAttributes"
@scope("prototype") @set
external assignConstructor: (Obj.t, unit => unit) => unit = "constructor"
@scope("prototype") @set
external assignAttributeChangedCallback: (Obj.t, (string, unit, string) => unit) => unit =
"attributeChangedCallback"
@scope("prototype") @set
external assignConnectedCallback: (Obj.t, unit => unit) => unit = "connectedCallback"
@scope("prototype") @set
external assignDisconnectedCallback: (Obj.t, unit => unit) => unit = "disconnectedCallback"
@scope("prototype") @set
external assignAddEventListener: (Obj.t, (event, event => unit) => unit) => unit =
"addEventListener"
@scope("prototype") @set
external assignRemoveEventListener: (Obj.t, (event, event => unit) => unit) => unit =
"removeEventListener"
@set
external assignObservedAttributes: (Obj.t, unit => array<string>) => unit = "observedAttributes"
@val external this: this = "this"
external toExtendedThis: this => extendedThis = "%identity"
@val external thisSuper: unit => unit = "this.super"
@set
external setThisProps: (this, Js.Dict.t<string>) => unit = "props"
)
let withAttrs = class => {
class->assignObservedAttributes(_ => [])
class->assignGetAttributes(_ => {
this.constructor.observedAttributes->Belt.Array.reduce(Js.Dict.empty(), (acc, attrName) => {
let attrValue = switch this.getAttribute(attrName)->Js.Nullable.toOption {
| Some(a) => Some(a)
| None => attrName == "style" ? Some(this.style) : None
}
let attrNameMap = attrName == "class" ? "className" : attrName
attrValue
->Belt.Option.map(
value => {
acc->Js.Dict.set(attrNameMap, value)
acc
},
)
->Belt.Option.getWithDefault(acc)
})
})
}
let withProps = class => {
class->assignGetPropsInProto(() => {
(this->toExtendedThis).getAttributes()
})
}
let withCreate = class => {
class->assignConstructor(() => {
thisSuper()
Js.log(this.constructor.name ++ " created")
(this->toExtendedThis).init()
})
}
let withInitAndUpdate = class => {
class->assignAttributeChangedCallback((name, _, value) => {
let extendedThis = this->toExtendedThis
this->setThisProps(extendedThis.getProps())
extendedThis.update(name, value)
Js.log(this.constructor.name ++ " update")
})
}
let withMountAndRender = class => {
class->assignConnectedCallback(_ => {
let extendedThis = this->toExtendedThis
if extendedThis.isConnected {
extendedThis.render->Js.Nullable.toOption->Belt.Option.forEach(fx => fx())
}
Js.log(this.constructor.name ++ " connected")
})
}
let withUnmount = class => {
class->assignDisconnectedCallback(_ => {
(this->toExtendedThis).dispose()
Js.log(this.constructor.name ++ " disconnected")
})
}
let withEventListener = class => {
class->assignAddEventListener((event, callback) => {
this.super.addEventListener(event, callback)
(this->toExtendedThis).object.on(event, callback)
})
class->assignRemoveEventListener((event, callback) => {
this.super.removeEventListener(event, callback)
(this->toExtendedThis).object.off(event, callback)
})
}

6
src/Init.res Normal file
View File

@ -0,0 +1,6 @@
let start = _ => {
let mockWindow = MockWindow.newWindow()
mockWindow->MockWindow.patchInsertBefore
let document = mockWindow->MockWindow.document
Js.log(document)
}

8
src/MockWindow.res Normal file
View File

@ -0,0 +1,8 @@
@module("./dom-mock/window") @new
external newWindow: unit => Dom.window = "Window"
@get
external document: Dom.window => Dom.document = "document"
@module("./dom-mock/window") @val
external patchInsertBefore: Dom.window => unit = "patchInsertBefore"

710
src/dom-mock/document.js Normal file
View File

@ -0,0 +1,710 @@
"use strict";
const Element_1 = (require("happy-dom/lib/nodes/element/Element"));
const HTMLUnknownElement_1 = (require("happy-dom/lib/nodes/html-unknown-element/HTMLUnknownElement"));
const Text_1 = (require("happy-dom/lib/nodes/text/Text"));
const Comment_1 = (require("happy-dom/lib/nodes/comment/Comment"));
const Node_1 = (require("happy-dom/lib/nodes/node/Node"));
const TreeWalker_1 = (require("happy-dom/lib/tree-walker/TreeWalker"));
const DocumentFragment_1 = (require("happy-dom/lib/nodes/document-fragment/DocumentFragment"));
const XMLParser_1 = (require("happy-dom/lib/xml-parser/XMLParser"));
const Event_1 = (require("happy-dom/lib/event/Event"));
const DOMImplementation_1 = (require("happy-dom/lib/dom-implementation/DOMImplementation"));
const Attr_1 = (require("happy-dom/lib/attribute/Attr"));
const NamespaceURI_1 = (require("happy-dom/lib/config/NamespaceURI"));
const DocumentType_1 = (require("happy-dom/lib/nodes/document-type/DocumentType"));
const ParentNodeUtility_1 = (require("happy-dom/lib/nodes/parent-node/ParentNodeUtility"));
const QuerySelector_1 = (require("happy-dom/lib/query-selector/QuerySelector"));
const DOMException_1 = (require("happy-dom/lib/exception/DOMException"));
const HTMLCollectionFactory_1 = (require("happy-dom/lib/nodes/element/HTMLCollectionFactory"));
const DocumentReadyStateEnum_1 = (require("happy-dom/lib/nodes/document/DocumentReadyStateEnum"));
const DocumentReadyStateManager_1 = (require("happy-dom/lib/nodes/document/DocumentReadyStateManager"));
const Selection_1 = (require("happy-dom/lib/selection/Selection"));
/**
* Document.
*/
class Document extends Node_1.default {
/**
* Creates an instance of Document.
*
* @param defaultView Default view.
*/
constructor(defaultView) {
super();
this.onreadystatechange = null;
this.nodeType = Node_1.default.DOCUMENT_NODE;
this.adoptedStyleSheets = [];
this.children = HTMLCollectionFactory_1.default.create();
this.readyState = DocumentReadyStateEnum_1.default.interactive;
this.isConnected = true;
this._activeElement = null;
this._isFirstWrite = true;
this._isFirstWriteAfterOpen = false;
this._cookie = '';
this._selection = null;
this.defaultView = defaultView //this.constructor._defaultView;
this.implementation = new DOMImplementation_1.default(this);
this._readyStateManager = new DocumentReadyStateManager_1.default(this.defaultView);
const doctype = this.implementation.createDocumentType('html', '', '');
const documentElement = this.createElement('html');
const bodyElement = this.createElement('body');
const headElement = this.createElement('head');
this.appendChild(doctype);
this.appendChild(documentElement);
documentElement.appendChild(headElement);
documentElement.appendChild(bodyElement);
}
/**
* Returns character set.
*
* @deprecated
* @returns Character set.
*/
get charset() {
return this.characterSet;
}
/**
* Returns character set.
*
* @returns Character set.
*/
get characterSet() {
const charset = this.querySelector('meta[charset]')?.getAttributeNS(null, 'charset');
return charset ? charset : 'UTF-8';
}
/**
* Last element child.
*
* @returns Element.
*/
get childElementCount() {
return this.children.length;
}
/**
* First element child.
*
* @returns Element.
*/
get firstElementChild() {
return this.children ? this.children[0] || null : null;
}
/**
* Last element child.
*
* @returns Element.
*/
get lastElementChild() {
return this.children ? this.children[this.children.length - 1] || null : null;
}
/**
* Returns cookie string.
*
* @returns Cookie.
*/
get cookie() {
return this._cookie;
}
/**
* Sets a cookie string.
*
* @param cookie Cookie string.
*/
set cookie(cookie) {
this._cookie = CookieUtility_1.default.getCookieString(this.defaultView.location, this._cookie, cookie);
}
/**
* Node name.
*
* @returns Node name.
*/
get nodeName() {
return '#document';
}
/**
* Returns <html> element.
*
* @returns Element.
*/
get documentElement() {
return ParentNodeUtility_1.default.getElementByTagName(this, 'html');
}
/**
* Returns document type element.
*
* @returns Document type.
*/
get doctype() {
for (const node of this.childNodes) {
if (node instanceof DocumentType_1.default) {
return node;
}
}
return null;
}
/**
* Returns <body> element.
*
* @returns Element.
*/
get body() {
return ParentNodeUtility_1.default.getElementByTagName(this, 'body');
}
/**
* Returns <head> element.
*
* @returns Element.
*/
get head() {
return ParentNodeUtility_1.default.getElementByTagName(this, 'head');
}
/**
* Returns CSS style sheets.
*
* @returns CSS style sheets.
*/
get styleSheets() {
const styles = (this.querySelectorAll('link[rel="stylesheet"][href],style'));
const styleSheets = [];
for (const style of styles) {
const sheet = style.sheet;
if (sheet) {
styleSheets.push(sheet);
}
}
return styleSheets;
}
/**
* Returns active element.
*
* @returns Active element.
*/
get activeElement() {
if (this._activeElement) {
let rootNode = (this._activeElement.getRootNode());
let activeElement = this._activeElement;
while (rootNode !== this) {
activeElement = rootNode.host;
rootNode = activeElement ? activeElement.getRootNode() : this;
}
return activeElement;
}
return this._activeElement || this.body || this.documentElement || null;
}
/**
* Returns scrolling element.
*
* @returns Scrolling element.
*/
get scrollingElement() {
return this.documentElement;
}
/**
* Returns location.
*
* @returns Location.
*/
get location() {
return this.defaultView.location;
}
/**
* Returns scripts.
*
* @returns Scripts.
*/
get scripts() {
return this.getElementsByTagName('script');
}
/**
* Returns base URI.
*
* @override
* @returns Base URI.
*/
get baseURI() {
const base = this.querySelector('base');
if (base) {
return base.href;
}
return this.defaultView.location.href;
}
/**
* Inserts a set of Node objects or DOMString objects after the last child of the ParentNode. DOMString objects are inserted as equivalent Text nodes.
*
* @param nodes List of Node or DOMString.
*/
append(...nodes) {
ParentNodeUtility_1.default.append(this, ...nodes);
}
/**
* Inserts a set of Node objects or DOMString objects before the first child of the ParentNode. DOMString objects are inserted as equivalent Text nodes.
*
* @param nodes List of Node or DOMString.
*/
prepend(...nodes) {
ParentNodeUtility_1.default.prepend(this, ...nodes);
}
/**
* Replaces the existing children of a node with a specified new set of children.
*
* @param nodes List of Node or DOMString.
*/
replaceChildren(...nodes) {
ParentNodeUtility_1.default.replaceChildren(this, ...nodes);
}
/**
* Query CSS selector to find matching elments.
*
* @param selector CSS selector.
* @returns Matching elements.
*/
querySelectorAll(selector) {
return QuerySelector_1.default.querySelectorAll(this, selector);
}
/**
* Query CSS Selector to find a matching element.
*
* @param selector CSS selector.
* @returns Matching element.
*/
querySelector(selector) {
return QuerySelector_1.default.querySelector(this, selector);
}
/**
* Returns an elements by class name.
*
* @param className Tag name.
* @returns Matching element.
*/
getElementsByClassName(className) {
return ParentNodeUtility_1.default.getElementsByClassName(this, className);
}
/**
* Returns an elements by tag name.
*
* @param tagName Tag name.
* @returns Matching element.
*/
getElementsByTagName(tagName) {
return ParentNodeUtility_1.default.getElementsByTagName(this, tagName);
}
/**
* Returns an elements by tag name and namespace.
*
* @param namespaceURI Namespace URI.
* @param tagName Tag name.
* @returns Matching element.
*/
getElementsByTagNameNS(namespaceURI, tagName) {
return ParentNodeUtility_1.default.getElementsByTagNameNS(this, namespaceURI, tagName);
}
/**
* Returns an element by ID.
*
* @param id ID.
* @returns Matching element.
*/
getElementById(id) {
return ParentNodeUtility_1.default.getElementById(this, id);
}
/**
* Returns an element by Name.
*
* @returns Matching element.
* @param name
*/
getElementsByName(name) {
const _getElementsByName = (_parentNode, _name) => {
const matches = HTMLCollectionFactory_1.default.create();
for (const child of _parentNode.children) {
if ((child.getAttributeNS(null, 'name') || '') === _name) {
matches.push(child);
}
for (const match of _getElementsByName(child, _name)) {
matches.push(match);
}
}
return matches;
};
return _getElementsByName(this, name);
}
/**
* Clones a node.
*
* @override
* @param [deep=false] "true" to clone deep.
* @returns Cloned node.
*/
cloneNode(deep = false) {
this.constructor._defaultView = this.defaultView;
const clone = super.cloneNode(deep);
if (deep) {
for (const node of clone.childNodes) {
if (node.nodeType === Node_1.default.ELEMENT_NODE) {
clone.children.push(node);
}
}
}
return clone;
}
/**
* Append a child node to childNodes.
*
* @override
* @param node Node to append.
* @returns Appended node.
*/
appendChild(node) {
// If the type is DocumentFragment, then the child nodes of if it should be moved instead of the actual node.
// See: https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment
if (node.nodeType !== Node_1.default.DOCUMENT_FRAGMENT_NODE) {
if (node.parentNode && node.parentNode['children']) {
const index = node.parentNode['children'].indexOf(node);
if (index !== -1) {
node.parentNode['children'].splice(index, 1);
}
}
if (node !== this && node.nodeType === Node_1.default.ELEMENT_NODE) {
this.children.push(node);
}
}
return super.appendChild(node);
}
/**
* Remove Child element from childNodes array.
*
* @override
* @param node Node to remove.
*/
removeChild(node) {
if (node.nodeType === Node_1.default.ELEMENT_NODE) {
const index = this.children.indexOf(node);
if (index !== -1) {
this.children.splice(index, 1);
}
}
return super.removeChild(node);
}
/**
* Inserts a node before another.
*
* @override
* @param newNode Node to insert.
* @param [referenceNode] Node to insert before.
* @returns Inserted node.
*/
insertBefore(newNode, referenceNode) {
const returnValue = super.insertBefore(newNode, referenceNode);
// If the type is DocumentFragment, then the child nodes of if it should be moved instead of the actual node.
// See: https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment
if (newNode.nodeType !== Node_1.default.DOCUMENT_FRAGMENT_NODE) {
if (newNode.parentNode && newNode.parentNode['children']) {
const index = newNode.parentNode['children'].indexOf(newNode);
if (index !== -1) {
newNode.parentNode['children'].splice(index, 1);
}
}
this.children.length = 0;
for (const node of this.childNodes) {
if (node.nodeType === Node_1.default.ELEMENT_NODE) {
this.children.push(node);
}
}
}
return returnValue;
}
/**
* Replaces the document HTML with new HTML.
*
* @param html HTML.
*/
write(html) {
const root = XMLParser_1.default.parse(this, html, true);
if (this._isFirstWrite || this._isFirstWriteAfterOpen) {
if (this._isFirstWrite) {
if (!this._isFirstWriteAfterOpen) {
this.open();
}
this._isFirstWrite = false;
}
this._isFirstWriteAfterOpen = false;
let documentElement = null;
let documentTypeNode = null;
for (const node of root.childNodes) {
if (node['tagName'] === 'HTML') {
documentElement = node;
}
else if (node.nodeType === Node_1.default.DOCUMENT_TYPE_NODE) {
documentTypeNode = node;
}
if (documentElement && documentTypeNode) {
break;
}
}
if (documentElement) {
if (!this.documentElement) {
if (documentTypeNode) {
this.appendChild(documentTypeNode);
}
this.appendChild(documentElement);
}
else {
const rootBody = root.querySelector('body');
const body = this.querySelector('body');
if (rootBody && body) {
for (const child of rootBody.childNodes.slice()) {
body.appendChild(child);
}
}
}
const body = this.querySelector('body');
if (body) {
for (const child of root.childNodes.slice()) {
if (child['tagName'] !== 'HTML' && child.nodeType !== Node_1.default.DOCUMENT_TYPE_NODE) {
body.appendChild(child);
}
}
}
}
else {
const documentElement = this.createElement('html');
const bodyElement = this.createElement('body');
const headElement = this.createElement('head');
for (const child of root.childNodes.slice()) {
bodyElement.appendChild(child);
}
documentElement.appendChild(headElement);
documentElement.appendChild(bodyElement);
this.appendChild(documentElement);
}
}
else {
const bodyNode = root.querySelector('body');
for (const child of (bodyNode || root).childNodes.slice()) {
this.body.appendChild(child);
}
}
}
/**
* Opens the document.
*
* @returns Document.
*/
open() {
this._isFirstWriteAfterOpen = true;
for (const eventType of Object.keys(this._listeners)) {
const listeners = this._listeners[eventType];
if (listeners) {
for (const listener of listeners) {
this.removeEventListener(eventType, listener);
}
}
}
for (const child of this.childNodes.slice()) {
this.removeChild(child);
}
return this;
}
/**
* Closes the document.
*/
close() { }
/* eslint-disable jsdoc/valid-types */
/**
* Creates an element.
*
* @param qualifiedName Tag name.
* @param [options] Options.
* @param [options.is] Tag name of a custom element previously defined via customElements.define().
* @returns Element.
*/
createElement(qualifiedName, options) {
return this.createElementNS(NamespaceURI_1.default.html, qualifiedName, options);
}
/**
* Creates an element with the specified namespace URI and qualified name.
*
* @param namespaceURI Namespace URI.
* @param qualifiedName Tag name.
* @param [options] Options.
* @param [options.is] Tag name of a custom element previously defined via customElements.define().
* @returns Element.
*/
createElementNS(namespaceURI, qualifiedName, options) {
const tagName = String(qualifiedName).toUpperCase();
let customElementClass;
if (this.defaultView && options && options.is) {
customElementClass = this.defaultView.customElements.get(String(options.is));
}
else if (this.defaultView) {
customElementClass = this.defaultView.customElements.get(tagName);
}
const elementClass = customElementClass || HTMLUnknownElement_1.default;
elementClass._ownerDocument = this;
const element = new elementClass();
element.tagName = tagName;
element.ownerDocument = this;
element.namespaceURI = namespaceURI;
if (element instanceof Element_1.default && options && options.is) {
element._isValue = String(options.is);
}
return element;
}
/* eslint-enable jsdoc/valid-types */
/**
* Creates a text node.
*
* @param [data] Text data.
* @returns Text node.
*/
createTextNode(data) {
Text_1.default._ownerDocument = this;
return new Text_1.default(data);
}
/**
* Creates a comment node.
*
* @param [data] Text data.
* @returns Text node.
*/
createComment(data) {
Comment_1.default._ownerDocument = this;
return new Comment_1.default(data);
}
/**
* Creates a document fragment.
*
* @returns Document fragment.
*/
createDocumentFragment() {
DocumentFragment_1.default._ownerDocument = this;
return new DocumentFragment_1.default();
}
/**
* Creates a Tree Walker.
*
* @param root Root.
* @param [whatToShow] What to show.
* @param [filter] Filter.
*/
createTreeWalker(root, whatToShow = -1, filter = null) {
return new TreeWalker_1.default(root, whatToShow, filter);
}
/**
* Creates an event.
*
* @deprecated
* @param type Type.
* @returns Event.
*/
createEvent(type) {
if (typeof this.defaultView[type] === 'function') {
return new this.defaultView[type]('init');
}
return new Event_1.default('init');
}
/**
* Creates an Attr node.
*
* @param name Name.
* @returns Attribute.
*/
createAttribute(name) {
const attribute = new Attr_1.default();
attribute.name = name.toLowerCase();
attribute.ownerDocument = this;
return attribute;
}
/**
* Creates a namespaced Attr node.
*
* @param namespaceURI Namespace URI.
* @param qualifiedName Qualified name.
* @returns Element.
*/
createAttributeNS(namespaceURI, qualifiedName) {
const attribute = new Attr_1.default();
attribute.namespaceURI = namespaceURI;
attribute.name = qualifiedName;
attribute.ownerDocument = this;
return attribute;
}
/**
* Imports a node.
*
* @param node Node to import.
* @param [deep=false] Set to "true" if the clone should be deep.
* @param Imported Node.
*/
importNode(node, deep = false) {
if (!(node instanceof Node_1.default)) {
throw new DOMException_1.default('Parameter 1 was not of type Node.');
}
const clone = node.cloneNode(deep);
clone.ownerDocument = this;
return clone;
}
/**
* Creates a range.
*
* @returns Range.
*/
createRange() {
return new this.defaultView.Range();
}
/**
* Adopts a node.
*
* @param node Node to adopt.
* @returns Adopted node.
*/
adoptNode(node) {
if (!(node instanceof Node_1.default)) {
throw new DOMException_1.default('Parameter 1 was not of type Node.');
}
const adopted = node.parentNode ? node.parentNode.removeChild(node) : node;
adopted.ownerDocument = this;
return adopted;
}
/**
* Returns selection.
*
* @returns Selection.
*/
getSelection() {
if (!this._selection) {
this._selection = new Selection_1.default(this);
}
return this._selection;
}
/**
* Returns a boolean value indicating whether the document or any element inside the document has focus.
*
* @returns "true" if the document has focus.
*/
hasFocus() {
return !!this.activeElement;
}
/**
* @override
*/
dispatchEvent(event) {
const returnValue = super.dispatchEvent(event);
if (event.bubbles && !event._propagationStopped) {
return this.defaultView.dispatchEvent(event);
}
return returnValue;
}
/**
* Triggered by window when it is ready.
*/
_onWindowReady() {
this._readyStateManager.whenComplete().then(() => {
this.readyState = DocumentReadyStateEnum_1.default.complete;
this.dispatchEvent(new Event_1.default('readystatechange'));
this.dispatchEvent(new Event_1.default('load', { bubbles: true }));
});
}
}
export default Document;
//# sourceMappingURL=Document.js.map

37
src/dom-mock/window.js Normal file
View File

@ -0,0 +1,37 @@
import Document from "./document";
import Node_1 from "happy-dom/lib/nodes/node/Node";
import CustomEvent_1 from "happy-dom/lib/event/events/CustomEvent";
import HTMLElement_1 from "happy-dom/lib/nodes/html-element/HTMLElement";
import CustomElementRegistry_1 from "happy-dom/lib/custom-element/CustomElementRegistry";
import EventTarget_1 from "happy-dom/lib/event/EventTarget";
export class Window extends EventTarget_1 {
constructor() {
super();
this.Node = Node_1;
this.CustomEvent = CustomEvent_1;
this.HTMLElement = HTMLElement_1;
this.customElements = new CustomElementRegistry_1();
const document = new Document(this)
this.document = document;
}
}
export const patchInsertBefore = (window) => {
/**
* Patch `insertBefore` function to default reference node to null when passed undefined.
* This is technically only needed for an Elm issue in version 1.0.2 of the VirtualDom
* More context here: https://github.com/elm/virtual-dom/issues/161
* And here: https://github.com/elm/virtual-dom/blob/1.0.2/src/Elm/Kernel/VirtualDom.js#L1409
*/
const insertBefore = window.Node.prototype.insertBefore
window.Node.prototype.insertBefore = function (...args) {
const [newNode, refNode] = args
const hasRefNode = args.length > 1
const isRefNodeDefined = typeof refNode !== 'undefined'
if (hasRefNode && !isRefNodeDefined)
return insertBefore.call(this, newNode, null)
return insertBefore.call(this, ...args)
}
}

View File

@ -1024,6 +1024,11 @@ css-unit-converter@^1.1.1:
resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21"
integrity sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==
css.escape@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==
css@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d"
@ -1449,6 +1454,18 @@ gzip-size@^6.0.0:
dependencies:
duplexer "^0.1.2"
happy-dom@^8.1.2:
version "8.1.2"
resolved "https://registry.yarnpkg.com/happy-dom/-/happy-dom-8.1.2.tgz#00b122500b6182f2bcd2d2e1c1659829aca27ff5"
integrity sha512-A/mTzD6KiVMWZynne7R+HlZjIpz9a1Ijh99inqq51Vis1v4G1K+mQeyOo19TXHtoFwAdjx+PzXQGpcyV0yhy9Q==
dependencies:
css.escape "^1.5.1"
he "^1.2.0"
node-fetch "^2.x.x"
webidl-conversions "^7.0.0"
whatwg-encoding "^2.0.0"
whatwg-mimetype "^3.0.0"
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
@ -1484,6 +1501,11 @@ hash-sum@^1.0.2:
resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04"
integrity sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==
he@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
highlight.js@^10.7.1:
version "10.7.3"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
@ -1503,6 +1525,13 @@ http-signature@~1.2.0:
jsprim "^1.2.2"
sshpk "^1.7.0"
iconv-lite@0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
dependencies:
safer-buffer ">= 2.1.2 < 3.0.0"
icss-utils@^5.0.0, icss-utils@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae"
@ -1918,6 +1947,13 @@ node-elm-compiler@^5.0.0:
lodash "^4.17.19"
temp "^0.9.0"
node-fetch@^2.x.x:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
dependencies:
whatwg-url "^5.0.0"
node-releases@^2.0.6:
version "2.0.8"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.8.tgz#0f349cdc8fcfa39a92ac0be9bc48b7706292b9ae"
@ -2325,7 +2361,7 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
@ -2605,6 +2641,11 @@ tough-cookie@~2.5.0:
psl "^1.1.28"
punycode "^2.1.1"
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
ts-dedent@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5"
@ -2681,6 +2722,11 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
vm-shim@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/vm-shim/-/vm-shim-0.0.6.tgz#5ce167f067017ff4f6f4ff646e10e0a6b3dd4ea3"
integrity sha512-KBCFEXbA/tuQN9e6D3eIGycDMaxsdJEG6+G3WkGupmJE40xVjJm1+pqizzgwSGqvwG/fghmJPUaWxYOTW1gfzw==
vue-hot-reload-api@^2.3.0:
version "2.3.4"
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
@ -2718,6 +2764,16 @@ watchpack@^2.4.0:
glob-to-regexp "^0.4.1"
graceful-fs "^4.1.2"
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
webidl-conversions@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a"
integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==
webpack-bundle-analyzer@^4.0.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.7.0.tgz#33c1c485a7fcae8627c547b5c3328b46de733c66"
@ -2807,6 +2863,26 @@ webpack-virtual-modules@^0.4.0:
watchpack "^2.4.0"
webpack-sources "^3.2.3"
whatwg-encoding@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53"
integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==
dependencies:
iconv-lite "0.6.3"
whatwg-mimetype@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7"
integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
which@^1.2.9:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"