--- a/devtools/client/inspector/markup/test/browser.ini
+++ b/devtools/client/inspector/markup/test/browser.ini
@@ -44,17 +44,16 @@ support-files =
events_bundle.js.map
events_original.js
head.js
helper_attributes_test_runner.js
helper_diff.js
helper_events_test_runner.js
helper_markup_accessibility_navigation.js
helper_outerhtml_test_runner.js
- helper_shadowdom.js
helper_style_attr_test_runner.js
lib_babel_6.21.0_min.js
lib_jquery_1.0.js
lib_jquery_1.1.js
lib_jquery_1.2_min.js
lib_jquery_1.3_min.js
lib_jquery_1.4_min.js
lib_jquery_1.6_min.js
--- a/devtools/client/inspector/markup/test/browser_markup_shadowdom.js
+++ b/devtools/client/inspector/markup/test/browser_markup_shadowdom.js
@@ -1,18 +1,14 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
-/* import-globals-from helper_shadowdom.js */
-
"use strict";
-loadHelperScript("helper_shadowdom.js");
-
requestLongerTimeout(2);
// Test a few static pages using webcomponents and check that they are displayed as
// expected in the markup view.
const TEST_DATA = [
{
// Test that expanding a shadow host shows a shadow root node and direct children.
@@ -201,17 +197,17 @@ const TEST_DATA = [
];
for (const {url, tree, title} of TEST_DATA) {
// Test each configuration in both open and closed modes
add_task(async function() {
info(`Testing: [${title}] in OPEN mode`);
await enableWebComponents();
const {inspector} = await openInspectorForURL(url.replace("#MODE#", "open"));
- await checkTreeFromRootSelector(tree, "test-component", inspector);
+ await assertMarkupViewAsTree(tree, "test-component", inspector);
});
add_task(async function() {
info(`Testing: [${title}] in CLOSED mode`);
await enableWebComponents();
const {inspector} = await openInspectorForURL(url.replace("#MODE#", "closed"));
- await checkTreeFromRootSelector(tree, "test-component", inspector);
+ await assertMarkupViewAsTree(tree, "test-component", inspector);
});
}
--- a/devtools/client/inspector/markup/test/browser_markup_shadowdom_clickreveal.js
+++ b/devtools/client/inspector/markup/test/browser_markup_shadowdom_clickreveal.js
@@ -1,18 +1,14 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
-/* import-globals-from helper_shadowdom.js */
-
"use strict";
-loadHelperScript("helper_shadowdom.js");
-
// Test that the corresponding non-slotted node container gets selected when clicking on
// the reveal link for a slotted node.
const TEST_URL = `data:text/html;charset=utf-8,
<test-component>
<div slot="slot1" id="el1">slot1-1</div>
<div slot="slot1" id="el2">slot1-2</div>
</test-component>
--- a/devtools/client/inspector/markup/test/browser_markup_shadowdom_delete.js
+++ b/devtools/client/inspector/markup/test/browser_markup_shadowdom_delete.js
@@ -1,18 +1,14 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
-/* import-globals-from helper_shadowdom.js */
-
"use strict";
-loadHelperScript("helper_shadowdom.js");
-
// Test that slot elements are correctly updated when slotted elements are being removed
// from the DOM.
const TEST_URL = `data:text/html;charset=utf-8,
<test-component>
<div slot="slot1" id="el1">slot1-1</div>
<div slot="slot1" id="el2">slot1-2</div>
</test-component>
@@ -40,40 +36,40 @@ add_task(async function() {
await waitForMultipleChildrenUpdates(inspector);
info("Test that expanding a shadow host shows shadow root and direct host children.");
const {markup} = inspector;
const hostContainer = markup.getContainer(hostFront);
const childContainers = hostContainer.getChildContainers();
is(childContainers.length, 3, "Expecting 3 children: shadowroot, 2 host children");
- checkText(childContainers[0], "#shadow-root");
- checkText(childContainers[1], "div");
- checkText(childContainers[2], "div");
+ assertContainerHasText(childContainers[0], "#shadow-root");
+ assertContainerHasText(childContainers[1], "div");
+ assertContainerHasText(childContainers[2], "div");
info("Expand the shadow root");
const shadowRootContainer = childContainers[0];
await expandContainer(inspector, shadowRootContainer);
const shadowChildContainers = shadowRootContainer.getChildContainers();
is(shadowChildContainers.length, 1, "Expecting 1 child slot");
- checkText(shadowChildContainers[0], "slot");
+ assertContainerHasText(shadowChildContainers[0], "slot");
info("Expand the slot");
const slotContainer = shadowChildContainers[0];
await expandContainer(inspector, slotContainer);
let slotChildContainers = slotContainer.getChildContainers();
is(slotChildContainers.length, 2, "Expecting 2 slotted children");
- slotChildContainers.forEach(container => checkSlotted(container));
+ slotChildContainers.forEach(container => assertContainerSlotted(container));
await deleteNode(inspector, "#el1");
slotChildContainers = slotContainer.getChildContainers();
is(slotChildContainers.length, 1, "Expecting 1 slotted child");
- checkSlotted(slotChildContainers[0]);
+ assertContainerSlotted(slotChildContainers[0]);
await deleteNode(inspector, "#el2");
slotChildContainers = slotContainer.getChildContainers();
// After deleting the last host direct child we expect the slot to show the default
// content <div>default</div>
is(slotChildContainers.length, 1, "Expecting 1 child");
ok(!slotChildContainers[0].isSlotted(), "Container is a not slotted container");
});
--- a/devtools/client/inspector/markup/test/browser_markup_shadowdom_maxchildren.js
+++ b/devtools/client/inspector/markup/test/browser_markup_shadowdom_maxchildren.js
@@ -1,18 +1,14 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
-/* import-globals-from helper_shadowdom.js */
-
"use strict";
-loadHelperScript("helper_shadowdom.js");
-
// Test that the markup view properly displays the "more nodes" button both for host
// elements and for slot elements.
const TEST_URL = `data:text/html;charset=utf-8,
<test-component>
<div>node 1</div><div>node 2</div><div>node 3</div>
<div>node 4</div><div>node 5</div><div>node 6</div>
</test-component>
@@ -43,61 +39,61 @@ add_task(async function() {
await waitForMultipleChildrenUpdates(inspector);
info("Test that expanding a shadow host shows shadow root and direct host children.");
const {markup} = inspector;
const hostContainer = markup.getContainer(hostFront);
let childContainers = hostContainer.getChildContainers();
is(childContainers.length, 6, "Expecting 6 children: shadowroot, 5 host children");
- checkText(childContainers[0], "#shadow-root");
+ assertContainerHasText(childContainers[0], "#shadow-root");
for (let i = 1; i < 6; i++) {
- checkText(childContainers[i], "div");
- checkText(childContainers[i], "node " + i);
+ assertContainerHasText(childContainers[i], "div");
+ assertContainerHasText(childContainers[i], "node " + i);
}
info("Click on the more nodes button under the host element");
let moreNodesLink = hostContainer.elt.querySelector(".more-nodes");
ok(!!moreNodesLink, "A 'more nodes' button is displayed in the host container");
moreNodesLink.querySelector("button").click();
await inspector.markup._waitForChildren();
childContainers = hostContainer.getChildContainers();
is(childContainers.length, 7, "Expecting one additional host child");
- checkText(childContainers[6], "div");
- checkText(childContainers[6], "node 6");
+ assertContainerHasText(childContainers[6], "div");
+ assertContainerHasText(childContainers[6], "node 6");
info("Expand the shadow root");
const shadowRootContainer = childContainers[0];
const shadowRootFront = shadowRootContainer.node;
await inspector.markup.expandNode(shadowRootFront);
await waitForMultipleChildrenUpdates(inspector);
const shadowChildContainers = shadowRootContainer.getChildContainers();
is(shadowChildContainers.length, 1, "Expecting 1 slot child");
- checkText(shadowChildContainers[0], "slot");
+ assertContainerHasText(shadowChildContainers[0], "slot");
info("Expand the slot");
const slotContainer = shadowChildContainers[0];
const slotFront = slotContainer.node;
await inspector.markup.expandNode(slotFront);
await waitForMultipleChildrenUpdates(inspector);
let slotChildContainers = slotContainer.getChildContainers();
is(slotChildContainers.length, 5, "Expecting 5 slotted children");
for (const slotChildContainer of slotChildContainers) {
- checkText(slotChildContainer, "div");
+ assertContainerHasText(slotChildContainer, "div");
ok(slotChildContainer.elt.querySelector(".reveal-link"),
"Slotted container has a reveal link element");
}
info("Click on the more nodes button under the slot element");
moreNodesLink = slotContainer.elt.querySelector(".more-nodes");
ok(!!moreNodesLink, "A 'more nodes' button is displayed in the host container");
EventUtils.sendMouseEvent({type: "click"}, moreNodesLink.querySelector("button"));
await inspector.markup._waitForChildren();
slotChildContainers = slotContainer.getChildContainers();
is(slotChildContainers.length, 6, "Expecting one additional slotted element");
- checkText(slotChildContainers[5], "div");
+ assertContainerHasText(slotChildContainers[5], "div");
ok(slotChildContainers[5].elt.querySelector(".reveal-link"),
"Slotted container has a reveal link element");
});
--- a/devtools/client/inspector/markup/test/browser_markup_shadowdom_mutations_shadow.js
+++ b/devtools/client/inspector/markup/test/browser_markup_shadowdom_mutations_shadow.js
@@ -1,18 +1,14 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
-/* import-globals-from helper_shadowdom.js */
-
"use strict";
-loadHelperScript("helper_shadowdom.js");
-
// Test that the markup view is correctly updated when elements under a shadow root are
// deleted or updated.
const TEST_URL = `data:text/html;charset=utf-8,
<test-component>
<div slot="slot1" id="el1">slot1-1</div>
<div slot="slot1" id="el2">slot1-2</div>
</test-component>
@@ -41,44 +37,44 @@ add_task(async function() {
#shadow-root
slot1-container
slot
div!slotted
div!slotted
another-div
div
div`;
- await checkTreeFromRootSelector(tree, "test-component", inspector);
+ await assertMarkupViewAsTree(tree, "test-component", inspector);
info("Delete a shadow dom element and check the updated markup view");
let mutated = waitForMutation(inspector, "childList");
ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
const shadowRoot = content.document.querySelector("test-component").shadowRoot;
const slotContainer = shadowRoot.getElementById("slot1-container");
slotContainer.remove();
});
await mutated;
const treeAfterDelete = `
test-component
#shadow-root
another-div
div
div`;
- await checkTreeFromRootSelector(treeAfterDelete, "test-component", inspector);
+ await assertMarkupViewAsTree(treeAfterDelete, "test-component", inspector);
mutated = inspector.once("markupmutation");
ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
const shadowRoot = content.document.querySelector("test-component").shadowRoot;
const shadowDiv = shadowRoot.getElementById("another-div");
shadowDiv.setAttribute("random-attribute", "1");
});
await mutated;
info("Add an attribute on a shadow dom element and check the updated markup view");
const treeAfterAttrChange = `
test-component
#shadow-root
random-attribute
div
div`;
- await checkTreeFromRootSelector(treeAfterAttrChange, "test-component", inspector);
+ await assertMarkupViewAsTree(treeAfterAttrChange, "test-component", inspector);
});
--- a/devtools/client/inspector/markup/test/browser_markup_shadowdom_noslot.js
+++ b/devtools/client/inspector/markup/test/browser_markup_shadowdom_noslot.js
@@ -1,18 +1,14 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
-/* import-globals-from helper_shadowdom.js */
-
"use strict";
-loadHelperScript("helper_shadowdom.js");
-
// Test that the markup view is correctly displayed when a component has children but no
// slots are available under the shadow root.
const TEST_URL = `data:text/html;charset=utf-8,
<style>
.has-before::before { content: "before-content" }
</style>
@@ -69,17 +65,17 @@ add_task(async function() {
#shadow-root
slot
div!slotted
div!slotted
class="not-nested"
class="nested"
class="has-before"
::before`;
- await checkTreeFromRootSelector(beforeTree, ".root", inspector);
+ await assertMarkupViewAsTree(beforeTree, ".root", inspector);
info("Move the non-slotted element with class has-before and check the pseudo appears");
const mutated = waitForNMutations(inspector, "childList", 2);
const pseudoMutated = waitForMutation(inspector, "nativeAnonymousChildList");
ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
const root = content.document.querySelector(".root");
const hasBeforeEl = content.document.querySelector("no-slot-component .has-before");
root.appendChild(hasBeforeEl);
@@ -103,10 +99,10 @@ add_task(async function() {
div!slotted
div!slotted
class="not-nested"
class="nested"
class="has-before"
::before
class="has-before"
::before`;
- await checkTreeFromRootSelector(afterTree, ".root", inspector);
+ await assertMarkupViewAsTree(afterTree, ".root", inspector);
});
--- a/devtools/client/inspector/markup/test/browser_markup_shadowdom_slotupdate.js
+++ b/devtools/client/inspector/markup/test/browser_markup_shadowdom_slotupdate.js
@@ -1,18 +1,14 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
-/* import-globals-from helper_shadowdom.js */
-
"use strict";
-loadHelperScript("helper_shadowdom.js");
-
// Test that slotted elements are correctly updated when the slot attribute is modified
// on already slotted elements.
const TEST_URL = `data:text/html;charset=utf-8,
<test-component>
<div slot="slot1">slot1-1</div>
<div slot="slot1">slot1-2</div>
<div slot="slot2" id="to-update">slot2-1</div>
@@ -43,17 +39,17 @@ add_task(async function() {
div!slotted
name="slot2"
div!slotted
div!slotted
slot1-1
slot1-2
slot2-1
slot2-2`;
- await checkTreeFromRootSelector(tree, "test-component", inspector);
+ await assertMarkupViewAsTree(tree, "test-component", inspector);
info("Listening for the markupmutation event");
const mutated = inspector.once("markupmutation");
ContentTask.spawn(gBrowser.selectedBrowser, {}, function() {
content.document.getElementById("to-update").setAttribute("slot", "slot1");
});
await mutated;
@@ -66,10 +62,10 @@ add_task(async function() {
div!slotted
div!slotted
name="slot2"
div!slotted
slot1-1
slot1-2
slot2-1
slot2-2`;
- await checkTreeFromRootSelector(mutatedTree, "test-component", inspector);
+ await assertMarkupViewAsTree(mutatedTree, "test-component", inspector);
});
--- a/devtools/client/inspector/markup/test/head.js
+++ b/devtools/client/inspector/markup/test/head.js
@@ -608,8 +608,167 @@ async function checkDeleteAndSelection(i
let node = await getNodeFront(selector, inspector);
ok(!node, "The node can't be found in the page anymore");
info("Undo the deletion to restore the original markup");
await undoChange(inspector);
node = await getNodeFront(selector, inspector);
ok(node, "The node is back");
}
+
+/**
+ * Temporarily flip all the preferences needed to enable web components.
+ */
+async function enableWebComponents() {
+ await pushPref("dom.webcomponents.shadowdom.enabled", true);
+ await pushPref("dom.webcomponents.customelements.enabled", true);
+}
+
+/**
+ * Assert whether the provided container is slotted.
+ */
+function assertContainerSlotted(container) {
+ ok(container.isSlotted(), "Container is a slotted container");
+ ok(container.elt.querySelector(".reveal-link"),
+ "Slotted container has a reveal link element");
+}
+
+/**
+ * Check if the provided text can be matched anywhere in the text content for the provided
+ * container.
+ */
+function assertContainerHasText(container, expectedText) {
+ const textContent = container.elt.textContent;
+ ok(textContent.includes(expectedText), "Container has expected text: " + expectedText);
+}
+
+/**
+ * Assert method to compare the current content of the markupview to a text based tree.
+ *
+ * @param {String} tree
+ * Multiline string representing the markup view tree, for instance:
+ * `root
+ * child1
+ * subchild1
+ * subchild2
+ * child2
+ * subchild3!slotted`
+ * Each sub level should be indented by 2 spaces.
+ * @param {String} selector
+ * A CSS selector that will uniquely match the "root" element from the tree
+ * @param {Inspector} inspector
+ * The inspector instance.
+ */
+async function assertMarkupViewAsTree(tree, selector, inspector) {
+ const {markup} = inspector;
+
+ info(`Find and expand the shadow DOM host matching selector ${selector}.`);
+ const rootFront = await getNodeFront(selector, inspector);
+ const rootContainer = markup.getContainer(rootFront);
+
+ const parsedTree = _parseMarkupViewTree(tree);
+ const treeRoot = parsedTree.children[0];
+ await _checkMarkupViewNode(treeRoot, rootContainer, inspector);
+}
+
+async function _checkMarkupViewNode(treeNode, container, inspector) {
+ const {node, children, path} = treeNode;
+ info("Checking [" + path + "]");
+ info("Checking node: " + node);
+
+ const slotted = node.includes("!slotted");
+ if (slotted) {
+ const nodeName = node.replace("!slotted", "");
+ assertContainerHasText(container, nodeName);
+ assertContainerSlotted(container);
+ } else {
+ assertContainerHasText(container, node);
+ }
+
+ if (!children.length) {
+ ok(!container.canExpand, "Container for [" + path + "] has no children");
+ return;
+ }
+
+ // Expand the container if not already done.
+ if (!container.expanded) {
+ await expandContainer(inspector, container);
+ }
+
+ const containers = container.getChildContainers();
+ is(containers.length, children.length,
+ "Node [" + path + "] has the expected number of children");
+ for (let i = 0; i < children.length; i++) {
+ await _checkMarkupViewNode(children[i], containers[i], inspector);
+ }
+}
+
+/**
+ * Helper designed to parse a tree represented as:
+ * root
+ * child1
+ * subchild1
+ * subchild2
+ * child2
+ * subchild3!slotted
+ *
+ * Lines represent a simplified view of the markup, where the trimmed line is supposed to
+ * be included in the text content of the actual markupview container.
+ * This method returns an object that can be passed to _checkMarkupViewNode() to verify
+ * the current markup view displays the expected structure.
+ */
+function _parseMarkupViewTree(inputString) {
+ const tree = {
+ level: 0,
+ children: []
+ };
+ let lines = inputString.split("\n");
+ lines = lines.filter(l => l.trim());
+
+ let currentNode = tree;
+ for (const line of lines) {
+ const nodeString = line.trim();
+ const level = line.split(" ").length;
+
+ let parent;
+ if (level > currentNode.level) {
+ parent = currentNode;
+ } else {
+ parent = currentNode.parent;
+ for (let i = 0; i < currentNode.level - level; i++) {
+ parent = parent.parent;
+ }
+ }
+
+ const node = {
+ node: nodeString,
+ children: [],
+ parent,
+ level,
+ path: parent.path + " " + nodeString
+ };
+
+ parent.children.push(node);
+ currentNode = node;
+ }
+
+ return tree;
+}
+
+function waitForMutation(inspector, type) {
+ return waitForNMutations(inspector, type, 1);
+}
+
+function waitForNMutations(inspector, type, count) {
+ info(`Expecting ${count} markupmutation of type ${type}`);
+ let receivedMutations = 0;
+ return new Promise(resolve => {
+ inspector.on("markupmutation", function onMutation(mutations) {
+ const validMutations = mutations.filter(m => m.type === type).length;
+ receivedMutations = receivedMutations + validMutations;
+ if (receivedMutations == count) {
+ inspector.off("markupmutation", onMutation);
+ resolve();
+ }
+ });
+ });
+}
+
deleted file mode 100644
--- a/devtools/client/inspector/markup/test/helper_shadowdom.js
+++ /dev/null
@@ -1,144 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* eslint no-unused-vars: [2, {"vars": "local"}] */
-
-/* import-globals-from head.js */
-
-"use strict";
-
-async function checkTreeFromRootSelector(tree, selector, inspector) {
- const {markup} = inspector;
-
- info(`Find and expand the shadow DOM host matching selector ${selector}.`);
- const rootFront = await getNodeFront(selector, inspector);
- const rootContainer = markup.getContainer(rootFront);
-
- const parsedTree = parseTree(tree);
- const treeRoot = parsedTree.children[0];
- await checkNode(treeRoot, rootContainer, inspector);
-}
-
-async function checkNode(treeNode, container, inspector) {
- const {node, children, path} = treeNode;
- info("Checking [" + path + "]");
- info("Checking node: " + node);
-
- const slotted = node.includes("!slotted");
- if (slotted) {
- checkSlotted(container, node.replace("!slotted", ""));
- } else {
- checkText(container, node);
- }
-
- if (!children.length) {
- ok(!container.canExpand, "Container for [" + path + "] has no children");
- return;
- }
-
- // Expand the container if not already done.
- if (!container.expanded) {
- await expandContainer(inspector, container);
- }
-
- const containers = container.getChildContainers();
- is(containers.length, children.length,
- "Node [" + path + "] has the expected number of children");
- for (let i = 0; i < children.length; i++) {
- await checkNode(children[i], containers[i], inspector);
- }
-}
-
-/**
- * Helper designed to parse a tree represented as:
- * root
- * child1
- * subchild1
- * subchild2
- * child2
- * subchild3!slotted
- *
- * Lines represent a simplified view of the markup, where the trimmed line is supposed to
- * be included in the text content of the actual markupview container.
- * This method returns an object that can be passed to checkNode() to verify the current
- * markup view displays the expected structure.
- */
-function parseTree(inputString) {
- const tree = {
- level: 0,
- children: []
- };
- let lines = inputString.split("\n");
- lines = lines.filter(l => l.trim());
-
- let currentNode = tree;
- for (const line of lines) {
- const nodeString = line.trim();
- const level = line.split(" ").length;
-
- let parent;
- if (level > currentNode.level) {
- parent = currentNode;
- } else {
- parent = currentNode.parent;
- for (let i = 0; i < currentNode.level - level; i++) {
- parent = parent.parent;
- }
- }
-
- const path = (parent.path ? parent.path + " " : "") + nodeString;
-
- const node = {
- node: nodeString,
- children: [],
- parent,
- level,
- path
- };
-
- parent.children.push(node);
- currentNode = node;
- }
-
- return tree;
-}
-
-function checkSlotted(container, expectedType = "div") {
- checkText(container, expectedType);
- ok(container.isSlotted(), "Container is a slotted container");
- ok(container.elt.querySelector(".reveal-link"),
- "Slotted container has a reveal link element");
-}
-
-function checkText(container, expectedText) {
- const textContent = container.elt.textContent;
- ok(textContent.includes(expectedText), "Container has expected text: " + expectedText);
-}
-
-function waitForMutation(inspector, type) {
- return waitForNMutations(inspector, type, 1);
-}
-
-function waitForNMutations(inspector, type, count) {
- info(`Expecting ${count} markupmutation of type ${type}`);
- let receivedMutations = 0;
- return new Promise(resolve => {
- inspector.on("markupmutation", function onMutation(mutations) {
- const validMutations = mutations.filter(m => m.type === type).length;
- receivedMutations = receivedMutations + validMutations;
- if (receivedMutations == count) {
- inspector.off("markupmutation", onMutation);
- resolve();
- }
- });
- });
-}
-
-/**
- * Temporarily flip all the preferences needed to enable web components.
- */
-async function enableWebComponents() {
- await pushPref("dom.webcomponents.shadowdom.enabled", true);
- await pushPref("dom.webcomponents.customelements.enabled", true);
-}