webcomponents / custom-elements Goto Github PK
View Code? Open in Web Editor NEWA polyfill for HTML Custom Elements v1
Home Page: https://www.webcomponents.org/polyfills
License: Other
A polyfill for HTML Custom Elements v1
Home Page: https://www.webcomponents.org/polyfills
License: Other
I see that there is this native-shim.js included which augments the native implementation to be compatible with ES5 code. However it is written in ES6, am i missing something here? Am i meant to transform this shim back into ES5.....
It does do what it says on the tin and ES6 compatible browsers are happy, however the ES5 ones which is the reason of this shim (from my understanding) are going to complain.
Hope someone can clarify for me?
Steps to reproduce:
native-shim.js
const element = document.createElement('div');
console.log(element instanceof HTMLElement); //output false
custom-elements/src/custom-elements.js
Line 768 in a0f55ec
In SVG, there are a lot of case-sensitive attribute names without namespaces. However, because setAttribute
converts them to lowercase, it fails silently and ends up setting the wrong attribute. Not to mention, this is pretty hard to notice even inspecting since the only difference is the capitalization of certain letters or if (like me) you don't have a lot of experience with SVG.
This is easy to work around though: element.setAttributeNS(null, 'caseSensitiveName', value)
.
Also, there doesn't seem to be a wrapper for setAttributeNS
and other NS
-suffixed functions. Is this intended?
Unfortunatly I cannot build the minified files. To install I did the following:
git clone https://github.com/webcomponents/custom-elements
cd custom-elements
npm i
(Instructions in the README.md are not updated yet I believe)
To build:
gulp
[18:19:30] Using gulpfile ~\code\custom-elements\gulpfile.js
[18:19:30] Starting 'default'...
However my tty returns to me without a "Finished" message. No directory is created and of course also no minified files.
See this example:
<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
<div id="myDiv"></div>
<script>
const el = document.querySelector('#myDiv');
// w/o timeout, has problems with _mainDocumentObserver which is null.
setTimeout(function() {
el.attachShadow({mode: 'open'});
el.parentNode.removeChild(el);
console.log(document.body.contains(el)); // false (correct)
console.log(el.parentNode); // <body> (should be null)
});
</script>
attachShadow
el
from its parent, el.parentNode
is not updatedMay be obvious to some, but was not to me. For native custom elements, can use the :defined
pseudo-class to style elements that have been defined (and probably more importantly, :not(:defined)
to style elements that haven't been).
Current fix I believe is to manually add and remove an "unresolved" attribute, or equivalent.
Object.setPrototypeOf
is unsupported in Safari < 9, IE < 11, and some older mobile browsers (full list) so calling it, as this library does, throws an error and fails to upgrade the element.
Example: https://jsfiddle.net/javan/fzynsLn7/
See the example's setPrototype
helper function for a potential fix.
Line 19 in 8b1c47f
This script will run when anyone installs webcomponents/custom-elements
via npm. This is not what you want, and makes it so that installation fails unless the person had bower installed globally. For example, in CI.
To work around this, I had to have Travis install bower globally.
I would suggest putting this command under another script so you do npm run bower
. I know this is less convenient ๐, but npm doesn't have any hooks that only run when working locally.
We've seen the native shim fail on Safari 10.1 where an element constructor that extended the patched HTMLElement
is being run via a call to the native customElements.define
, and not through the patched customElements.define
(which ensures constructorByTagname
is properly set). This should be impossible given the code since both defining window.HTMLElement
and patching customElements.define
occur synchronously in the same script. As such, it can probably be explained by a native object wrapper being garbage collected.
We believe we've found a workaround by using Object.define
on window.customElements
as well as customElements.define
and customElements.get
to do the patch. With this change, we've let it run on an automated loop for >1000 reloads and haven't seen the issue). Will submit PR for that.
In the src/README.md
, it says:
The implementation should work without additional polyfills in IE 11, Edge, Safari >6, Firefox, Chrome, Android Browser >4.4, and Opera (not Mini).
IE 10 should be supported with the Mutation Observer polyfill.
However, IE10 support not only requires Mutation Observer polyfill, but also polyfills for new ES2015 globals such as Map
as the current build doesn't polyfill Map
. Thus, in order to make the polyfill work in IE10, users also need to load core-js or other similar libraries.
I'm working on getting the custom elements polyfill included into Polyfill.io, and noticed that the latest release that's available on NPM is alpha 3, despite alpha 4 being tagged on Github. Is there a reason the latest isn't on NPM yet? If not, would you mind pushing the update to there as well? I'd rather not link to Github for the dependency if I can avoid it.
This would remove the need for users to decide which part of the polyfill they need to load. The polyfill (which is very small) could simply always be loaded regardless of whether the browser supports custom-elements or not and the code is ES5 or ES6. The native-shim
should probably continue to be available standalone for users that want the smallest possible code download to a given client.
In this case the HTMLElement
global would likely always need to be patched. Additionally, it might be necessary to turn on native shimming globally when any ES5 class is defined.
Currently the polyfill uses global (and in the case of Shadow DOM, local per root) MutationObservers to detect connection and disconnection of custom elements. This results in async connectedCallback
and disconnectedCallback
, whereas native implementations run these callbacks at "nanotask" timing, synchronous to the DOM mutation method that added/removed the node. The differences in timing between native and polyfill are often sources of confusion and complexity.
It should be possible to match the spec timing by globally patching the methods that can add/remove nodes from the main document and doing the walks to run connectedCallback
/disconnectedCallback
s synchronous to those methods:
appendChild
insertBefore
removeChild
remove
replaceChild
innerHTML
accessorThis is theoretically no worse in performance than the MO since the exact same treewalk must be done in either case.
The main "hard problem" with this approach is that innerHTML
is an accessor that can result in added/removed nodes, and some older browsers make this difficult:
innerHTML
accessor on the HTMLElement.prototype
, but rather incorrectly place these accessors on instances, hence it's not as simple as patching HTMLElement.prototype.innerHTML
, andinnerHTML
accessor does not provide access to the underlying set
/get
accessor methods, so once patched to implement scanning for custom elements to connect/disconnect, "tricks" must be used to actually do the normal innerHTML
work.Looks like IE doesn't recognize my custom component as function (even while outputting it in console as [object function]) and returning false for instanceof Function.
I was trying to wrap component in function that will return newly created component, but got same error as soon as set my component's prototype for it.
function constr() {
return Reflect.construct(component, []);
}
Object.setPrototypeOf(constr, component);
Object.setPrototypeOf(constr.prototype, component.prototype);
customElements.define(component.tagName, constr);
Did someone met this problem and found any possible solution?
I'm getting this error while attempting to do a simple custom-element using webpack.
My setup:
<script src="/custom-elements.min.js"></script>
<script src="/native-shim.js"></script>
export default class TodoApp extends HTMLElement {
constructor () {
super();
console.log('CONSTRUCT');
}
}
The error happens on line 98 of native-shim:
window.HTMLElement = function() {
if (!browserConstruction) {
const tagname = tagnameByConstructor.get(this.constructor);
const fakeClass = nativeGet.call(window.customElements, tagname);
// Make sure that the fake constructor doesn't call back to this constructor
userConstruction = true;
const instance = new (fakeClass)();
return instance;
}
// Else do nothing. This will be reached by ES5-style classes doing
// HTMLElement.call() during initialization
browserConstruction = false;
};
"tagname" is undefined.
I've tried different version of babel, including "latest". I've tried changing the order of the shims and excluding the native shim.
I am trying to use the custom elements v1 polyfill (custom-elements.min.js) in an angular-cli project.
custom-elements.min.js works across all browsers except IE10. The polyfill works fine when loaded through script
tag in a non angular-cli web app. However, in angular-cli generated projects, it logs the following error:
SCRIPT5009: 'Map' is undefined
I've included custom-elements.min.js as a third-party library in my angular-cli.json as follows:
"scripts": [
"../node_modules/mutationobserver-shim/dist/mutationobserver.min.js",
"../node_modules/@webcomponents/custom-elements/custom-elements.min.js"
],
As the error was pointing at Map
in custome-elements.min.js, I included es6-shim.js before the polyfill and it started working now in IE10.
"scripts": [
"../node_modules/es6-shim/es6-shim.min.js",
"../node_modules/mutationobserver-shim/dist/mutationobserver.min.js",
"../node_modules/@webcomponents/custom-elements/custom-elements.min.js"
],
However, I don't want to use es6-shim
because it does work fine with no es6-shim in IE10 when it gets included normally in the script
tag. I am assuming the angular-cli(or webpack) might be doing something that's unknown to me at this point. What could be possible causes of this error? I know that the polyfill is in ES5 so I am sure that it shouldn't require ES6-shim.
The log error was pointing at the polyfill (https://github.com/webcomponents/custom-elements/blob/master/custom-elements.min.js).
From @WebReflection on August 14, 2016 13:28
It seems like it's possible to class MyElement extends HTMLElement {}
and then document.body.appendChild(new MyElement)
after defining the element through customElements.define('my-element', MyElement)
.
However, if I try to do the same, using {extends: ...}
or not, I cannot create new custom elements in the same way.
class MyAnchor extends HTMLAnchorElement {}
customElements.define('my-a', MyAnchor);
// or
customElements.define('my-a', MyAnchor, {extends: 'a'});
// will fail
document.body.appendChild(new MyAnchor);
I wonder if it's in the pipeline to monkey-patch all HTML constructors like it's done already only for few of them, or if the usage of new CustomElement
instead of document.createElement('a', {is: 'my-a'})
will be discourage due polyfill limits (I personally wouldn't polyfill every DOM methods that might accept a generic node as one of its arguments).
Thanks for any sort of clarification.
Copied from original issue: webcomponents/webcomponentsjs#595
This is occurring when building app via webpack and uglify
Unexpected token: name (browserConstruction) [../~/source-map-loader!../~/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js:89,0]
https://travis-ci.org/Hotell/skate-starter/builds/236986916#L306
any ideas?
These lines cause a syntax error in Chrome 53:
HTMLElement.prototype = Object.create(origHTMLElement.prototype, {
constructor, {value: HTMLElement, configurable: true, writable: true}, // THIS LINE
});
This may come of as pedantic but I don't mean it to be.
The documentation says "Android Browser >4.4" should be supported. Should it be "Android Browser โฅ4.4"?
ShadowRoot.prototype.innerHTML
isn't patched. This prevents custom elements created by setting it from being upgraded at the right time. (See webcomponents/webcomponentsjs#717.)
I'd like to see the shim be kept as small as possible, and believe it would be beneficial for the HTML Imports to be their own shim. This also seems to be a valid path seeing as Imports are one of the specs that is still under contention.
For my use case, I plan to not use Imports and instead use (SystemJS) ES modules, and template strings.
Hey there,
I'm having some trouble getting this polyfill + native-shim to work right across all devices.
Some background on my setup:
node_module
written in ES2015, which creates CustomElements
used in the appSo the relevant webpack dev config looks something like this:
const config = webpackMerge(baseConfig, {
entry: [
'webpack/hot/only-dev-server',
'@webcomponents/custom-elements/src/native-shim',
'@webcomponents/custom-elements',
'<module that uses CustomElements>/dist/src/main',
'./src/client',
],
output: {
path: path.resolve(__dirname, './../dist/assets/'),
filename: 'app.js',
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
options: {
cacheDirectory: true,
},
include: [
path.join(NODE_MODULES_DIR, '<module that uses CustomElements>'),
path.join(__dirname, '../src'),
],
},
],
},
...
key take aways:
<module that uses CustomElements>
<module that uses CustomElements>
loaded before my app soure<module that uses CustomElements>
is ES6 so we're transpiling it ( thus the include in the babel-loader
).The above works as-expected in modern ES6 browsers ( IE desktop Chrome ).
HOWEVER
I get the following error in older browsers, for example iOS 8:
SyntaxError: Unexpected token ')'
pointing to the opening anonymous function in the native-shim pollyfill:
(() => {
'use strict';
// Do nothing if `customElements` does not exist.
if (!window.customElements) return;
const NativeHTMLElement = window.HTMLElement;
const nativeDefine = window.customElements.define;
const nativeGet = window.customElements.get;
So it seems to me like the native-shim
would need to be transpiled to ES5:
include: [
+ path.join(NODE_MODULES_DIR, '@webcomponents/custom-elements/src/native-shim'),
path.join(NODE_MODULES_DIR, '<module that uses CustomElements>'),
path.join(__dirname, '../src'),
],
...but doing so now breaks both Chrome and iOS 8 with the following error:
app.js:1 Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
at new StandInElement (native-shim.js:122)
at HTMLDocument.createElement (<anonymous>:1:1545)
at ReactDOMComponent.mountComponent (ReactDOMComponent.js:504)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at Object.updateChildren (ReactChildReconciler.js:121)
at ReactDOMComponent._reconcilerUpdateChildren (ReactMultiChild.js:208)
at ReactDOMComponent._updateChildren (ReactMultiChild.js:312)
.. which takes me to this constructor()
line in the native-shim:
window.customElements.define = (tagname, elementClass) => {
const elementProto = elementClass.prototype;
const StandInElement = class extends NativeHTMLElement {
constructor() {
Phew. So it's very unclear to me how we actually include this in a webpack based build, where the dependency using CustomElements is ES6 ( and needs transpiling).
I'm really quite frustrated with web components at this point. I just want to use this one dependency that happens to be built with web components. How can I get it to work properly in a webpack build, and work across all devices? Am I missing something obvious here?
My .babelrc config for posterity sake (dev config most relevant):
{
"presets": [
["es2015", { "modules": false }],
"react"
],
"plugins": [
"transform-custom-element-classes",
"transform-object-rest-spread",
"transform-object-assign",
"transform-exponentiation-operator"
],
"env": {
"test": {
"plugins": [
[ "babel-plugin-webpack-alias", { "config": "./cfg/test.js" } ]
]
},
"dev": {
"plugins": [
"react-hot-loader/babel",
[ "babel-plugin-webpack-alias", { "config": "./cfg/dev.js" } ]
]
},
"dist": {
"plugins": [
[ "babel-plugin-webpack-alias", { "config": "./cfg/dist.js" } ],
"transform-react-constant-elements",
"transform-react-remove-prop-types",
"minify-dead-code-elimination",
"minify-constant-folding"
]
},
"production": {
"plugins": [
[ "babel-plugin-webpack-alias", { "config": "./cfg/server.js" } ],
"transform-react-constant-elements",
"transform-react-remove-prop-types",
"minify-dead-code-elimination",
"minify-constant-folding"
]
}
}
}
Its been a while and lots of changes occurring - do you have an RC that we can start using?
I made a new default app using the polymer starter kit and I built it using the es5-bundled preset. Will not work in IE11. Works fine in Chrome. Am I not understanding something with the support with polyfills or is this a bug?
Also getting this in console:
โUnable to get property โpushโ of undefined or null reference" inside of CustomElementInternal.js (255,7)
This is for v1.0.0-rc.1 and also v1.0.0-alpha.4.
When running tests with PhantomJS 2.1.14, this error is thrown:
TypeError: Attempting to configurable attribute of unconfigurable property.
at dist/components/idx-nwc/dist/webcomponents/custom-elements.min.js:18
Error first appeared in v1.0.0-alpha.4.
From @blasten on September 19, 2016 17:8
Using the v1, the following assertion fails:
assert.isTrue(document.documentElement instenceof HTMLElement);
/cc @justinfagnani
Copied from original issue: webcomponents/webcomponentsjs#623
Currently this callback is called only when the value of the attribute has changed. Spec says to call it even when the value hasn't changed.
https://www.w3.org/TR/custom-elements/#concept-element-attributes-change
https://bugs.chromium.org/p/chromium/issues/detail?id=676247
It is really strange how this code works in Chrome (v55):
class CustomElement extends HTMLElement {}
customElements.define('custom-element', CustomElement);
// with lowercase works - logs "true"
console.log('works:', Object.getPrototypeOf(
document.createElement('custom-element')
) === CustomElement.prototype);
// with uppercase breaks - logs "false"
console.log('breaks:', Object.getPrototypeOf(
document.createElement('CUSTOM-ELEMENT')
) === CustomElement.prototype);
document.createElement
when used with lowercase tagName works with custom element, but when used with uppercase it doesn't...
Polyfill works with both cases. MDN for createElement
says:
When called on an HTML document, createElement() converts tagName to lower case before creating the element.
Is this a bug in Chrome? Or is this a tricky feature of custom elements? This is a problem especially for using tools like virtual-dom
, which uppercase tagName when creating elements from virtual nodes, so it is impossible to use it for custom elements.
Andrea's polyfill has a caveat in how Custom Element constructors are defined and used.
Does this polyfill have the same (or similar) caveat? If so, what are the recommendations for end users?
From @trusktr on June 1, 2016 8:27
I see the line
HTMLElement.prototype = Object.create(origHTMLElement);
But should it be
HTMLElement.prototype = Object.create(origHTMLElement.prototype);
? If the prototype is the origHTMLElement
, that would mean that the origHTMLElement.*
static properties will be HTMLElement instance properties?
Copied from original issue: webcomponents/webcomponentsjs#546
Custom elements inserted via insertAdjacentHTML
are ignored / never upgraded.
diff --git a/tests/html/Element/index.html b/tests/html/Element/index.html
index b771d37..872b872 100644
--- a/tests/html/Element/index.html
+++ b/tests/html/Element/index.html
@@ -9,5 +9,6 @@
'./removeAttribute.html',
'./removeAttributeNS.html',
'./insertAdjacentElement.html',
+ './insertAdjacentHTML.html'
]);
</script>
diff --git a/tests/html/Element/insertAdjacentHTML.html b/tests/html/Element/insertAdjacentHTML.html
new file mode 100644
index 0000000..8dca1e6
--- /dev/null
+++ b/tests/html/Element/insertAdjacentHTML.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<html>
+<head>
+<title>Element#insertAdjacentHTML</title>
+<script>
+ (window.customElements = window.customElements || {}).forcePolyfill = true;
+</script>
+<script src="../../../../es6-promise/dist/es6-promise.auto.min.js"></script>
+<script src="../../../../web-component-tester/browser.js"></script>
+<script src="../../../custom-elements.min.js"></script>
+</head>
+<body>
+<script>
+function generateLocalName() {
+ return 'test-element-' + Math.random().toString(32).substring(2);
+}
+
+function defineWithLocalName(localName, observedAttributes) {
+ customElements.define(localName, class extends HTMLElement {
+ constructor() {
+ super();
+ this.constructed = true;
+ this.connectedCallbackCount = 0;
+ this.disconnectedCallbackCount = 0;
+ }
+
+ connectedCallback() {
+ this.connectedCallbackCount++;
+ }
+
+ disconnectedCallback() {
+ this.disconnectedCallbackCount++;
+ }
+ });
+}
+
+suite('Custom elements in HTML strings are created using `insertAdjacentHTML`.', function() {
+ let localName;
+
+ setup(function() {
+ localName = generateLocalName();
+ defineWithLocalName(localName);
+ });
+
+ test('Disconnected context', function() {
+ const div = document.createElement('div');
+ div.insertAdjacentHTML('beforeend', `<${localName}></${localName}>`);
+
+ assert.equal(div.childNodes.length, 1);
+ assert.equal(div.childNodes[0].localName, localName);
+ assert.equal(div.childNodes[0].constructed, true);
+ assert.equal(div.childNodes[0].connectedCallbackCount, 0);
+ assert.equal(div.childNodes[0].disconnectedCallbackCount, 0);
+ });
+
+ test('Connected context', function() {
+ const div = document.createElement('div');
+ document.body.appendChild(div);
+ div.insertAdjacentHTML('beforeend', `<${localName}></${localName}>`);
+
+ assert.equal(div.childNodes.length, 1);
+ assert.equal(div.childNodes[0].localName, localName);
+ assert.equal(div.childNodes[0].constructed, true);
+ assert.equal(div.childNodes[0].connectedCallbackCount, 1);
+ assert.equal(div.childNodes[0].disconnectedCallbackCount, 0);
+
+ document.body.removeChild(div);
+ });
+});
+</script>
+</body>
+</html>
In the following case, the polyfill does not work because the functions it patches on the DOM (such as document.createElement
) are never actually called:
<html>
<body>
<script>
var originalCreateElement = document.createElement;
document.createElement = function() {
console.log("Someone else doing something by patching the DOM");
return originalCreateElement.apply(this, arguments);
}
customElements.forcePolyfill = true;
</script>
<script src="https://raw.githubusercontent.com/webcomponents/custom-elements/master/custom-elements.min.js"></script>
</body>
</html>
I discovered this because I have the LastPass chrome extension, which patches document.createElement
as above. The reason why there is a bug is because the CE polyfill patches Document.prototype
instead of patching document.createElement
directly. In the example above, originalCreateElement
is a reference to the native createElement
, so when originalCreateElement.apply(this, arguments)
is called, it calls the native implementation without calling the patched version that CE polyfill puts onto Document.prototype.
Another way of wording this is that patching Document.prototype
assumes that document
will actually use its prototype's implementation of createElement
, instead of document
having its own property called createElement
.
I see this as a pretty crucial bug to fix, since patching createElement with document.createElement =
is a common practice. I'm still thinking about what the full fix for this is, though. If we change the polyfill code to also patch document.createElement =
directly, then that may leave out other Document
instances. But if you don't patch it that way, then you're in trouble if anybody else on the page is doing so.
Is the CustomElements.js similar to @webcomponents/custom-elements/custom-elements.min.js ? What is the difference? @webcomponents/custom-elements/custom-elements.min.js was working, but the CustomElements.js in this directory not working.
Hello,
On the custom-element
polyfill, the function attributeChangedCallback
is called twice when an attribute, listed in the observedAttributes()
, is changed.
<my-component id="compo" foo="bar"></my-component>
<button id="myBtn">Change value</button>
class MyComponent extends HTMLElement {
constructor() {
super();
}
static get observedAttributes() { return ['foo']; }
attributeChangedCallback(attrName, oldVal, newVal) {
console.log('[my component] attribute', attrName, 'changed from', oldVal, 'to', newVal);
}
}
window.customElements.define('my-component', MyComponent);
The logs are as follows:
[my component] attribute foo changed from null to bar
click on the button to change the attribute value
[my component] attribute foo changed from bar to baz
[my component] attribute foo changed from bar to baz
As you can see, the line [my component] attribute foo changed from bar to baz
is called twice.
Here is a JsFiddle to test that example: https://jsfiddle.net/czo1355c/
The issue is encountered on a Chrome v53, since starting with v54, customElements
is natively supported by Chrome (and the function attributeChangedCallback
is only called once).
Tested against version 1.0.0-alpha.3
of custom-element library.
Thanks
At load time, var customElements = new CustomElementRegistry(internals);
is called which calls this._documentConstructionObserver = new DocumentConstructionObserver(internals, document);
which in turn calls this._internals.patchAndUpgradeTree(this._document);
which walks the tree and ends up calling gatherElements()
.
But gatherElements()
has code including:
var gatherElements = function gatherElements(element) {
if (element.localName === 'link' && element.getAttribute('rel') === 'import') {
var importNode = element.import;
However, if relying on the html-imports
polyfill, the function flatten()
in that module only runs once a given import has loaded. And, apparently, it is flatten()
that is responsible for adding the import
property to a link
element. Yet custom-elements
seems to be assuming that the .import
property is available on a link
element earlier. It isn't.
Another way of saying this is that it seems that custom-elements
is maybe mostly tested on Chrome where HTMLImports is native. For testing custom-elements
with the html-imports
polyfill, it might make sense on Chrome to execute delete HTMLLinkElement.prototype.import;
at the top of the test to make sure custom-elements
works well with polyfilled HTMLImports. html-imports
looks for import
to set its useNative
flag. Forcing use of the html-imports
polyfill would better emulate IE/Edge.
So, I am grasping the v1 specs for custom elements.Something that confuses me, is the element registration
window.customElements.define('my-div', MyDiv, {extends: 'div'});
Now, if the custom element extends the HTMLDivElement,
class myDiv extends HTMLDivElement{}
Isnt it counter intuitive that I should specify the extends attribute as a third paramaeter?
I know it helps in identifying which element it extends, specifically, but the grammar
class myDiv extends HTMLDivElement{}
itself, is pretty specific isn't it?
it is like we have the word regardless, but we need a new word irregardless , regardless of the fact that it does nothing but mean the same as regardless!
I get Custom Elements: Element#attachShadow
was not patched error.
Works fine on Chrome.
https://www.masons-foundation.org/home/feed/
FireFox 51 and poly v 1.04a - both latest.
SVG elements have attributes like "viewBox", but native-shim's setAttribute is lowercasing all attribute names. It's interfering with my ability to use SVG elements!
If you use this polyfill as standalone (e.g. not using the whole webcomponentsjs pack) there is always a message in the console:
https://github.com/webcomponents/custom-elements/blob/master/src/Patch/Element.js#L26
Will it be possible to remove this warning, at least for production code?
Its just a question. The native-shim solves only the ES6 (extends HTMLElement) compile to ES5 issue? What about with other "native elements" (see below examles) in customElements v1?
e.g.
class Foo extends HTMLFormElement {}
class Bar extends HTMImageElement {}
class Baz extends HTMLUListElement {}
In my current project i use customElements v0 and the above examples works well.
Repro: http://jsbin.com/jusodew/edit?html,output.
NotSupportedError (DOM Exception 9): A newly constructed custom element must not have child nodes
. If the polyfill is removed, it works as expected. That seems odd: if native CE is available, the polyfill should stay out of the way, no?If this looks like a WebKit bug, let me know and I can file one for it.
From @warnerandy on August 3, 2016 18:32
I am seeing this error on occasion at page load. I'm only using the custom elements v1 polyfill in this scenario.
Copied from original issue: webcomponents/webcomponentsjs#586
See http://jsbin.com/tetika/3/edit?html,console,output.
In Canary and STP (with CE turned on), the connectedCallback
is invoked as expected.
In production Chrome, Firefox, Safari, the connectedCallback
is not invoked.
This is using the current webcomponents-lite.js from the v1 branch of webcomponents/webcomponentsjs.
The current polyfill uses lots of MutationObservers try to catch all of the dom manipulations that could cause an element to need to customize. Unfortunately, this results in a significant amount of overhead and hinders performance.
Here's a quick perf check demo:
native (Chrome only): http://output.jsbin.com/bejawep
polyfill: http://output.jsbin.com/teveman
polyfill modified to not use as many MutationObservers: http://output.jsbin.com/xacefo
other polyfill for comparison: http://output.jsbin.com/tewesi
Please publish it ๐
I'd like the option to run cleanly on IE11 using only Custom Elements, HTML Import, and Template. So...no shadow DOM or Shady DOM polyfill. Everything looks good, with the exception of this one warning in PatchElement
:
var PatchElement = function (internals) {
if (Native.Element_attachShadow) {
setPropertyUnchecked(Element.prototype, 'attachShadow', function (init) {
var shadowRoot = Native.Element_attachShadow.call(this, init);
this.__CE_shadowRoot = shadowRoot;
return shadowRoot;
});
} else {
console.warn('Custom Elements: `Element#attachShadow` was not patched.');
}
It would be nice to have some option to suppress this warning.
Using custom-elements through webcomponents transpiled to ES5 fails under IE11 when trying to upgrade elements on the page. What seems to happen is I hit https://github.com/webcomponents/custom-elements/blob/master/src/CustomElementInternals.js#L248, and the test fails because element
is HTMLUnknownElement
and result
is of type AppDrawer
.
I see
custom-elements/tests/js/typescript.js
Line 16 in a0f55ec
Is Typescript/ES5 supported in the v1 branch currently or am I doing something wrong?
<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.0-rc.8/webcomponents-lite.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.0-rc.8/custom-elements-es5-adapter.js"></script>
<script src="bundle.js"></script>
</head>
<body>
<app-drawer open></app-drawer>
</body>
</html>
bundle.js
is transpiled down to:
(function () {
'use strict';
function __$styleInject(css) {
if (!css) return;
if (typeof window == 'undefined') return;
var style = document.createElement('style');
style.setAttribute('media', 'screen');
style.innerHTML = css;
document.head.appendChild(style);
return css;
}
__$styleInject("app-drawer {\n color: red;\n}\n");
function __extends(d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var AppDrawer = (function (_super) {
__extends(AppDrawer, _super);
function AppDrawer() {
_super.call(this);
}
Object.defineProperty(AppDrawer.prototype, "open", {
get: function () {
return this.hasAttribute("open");
},
set: function (val) {
val ? this.setAttribute("open", '') : this.removeAttribute('open');
},
enumerable: true,
configurable: true
});
Object.defineProperty(AppDrawer, "observedAttributes", {
get: function () { return ["open"]; },
enumerable: true,
configurable: true
});
AppDrawer.prototype.connectedCallback = function () {
var _this = this;
this.addEventListener("click", function () {
_this.open = !_this.open;
});
this.textContent = this.open ? "OPEN" : "CLOSED";
};
AppDrawer.prototype.attributeChangedCallback = function (attr, oldVal, newVal) {
this.textContent = this.open ? "OPEN" : "CLOSED";
};
return AppDrawer;
}(HTMLElement));
customElements.define("app-drawer", AppDrawer);
}());
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.