Coder Social home page Coder Social logo

custom-elements's Introduction

custom-elements's People

Contributors

aomarks avatar bicknellr avatar cronon avatar denisw avatar dfreedm avatar ebidel avatar fluorescenthallucinogen avatar grimly avatar joeldenning avatar justinfagnani avatar kevinpschaaf avatar limonte avatar matthewp avatar rictic avatar robdodson avatar ruphin avatar shijir avatar snuggs avatar timvdlippe avatar valdrinkoshi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

custom-elements's Issues

Native createElement doesn't create custom element with proper tag name

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);

Live example

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.

Element#insertAdjacentHTML is unsupported

Custom elements inserted via insertAdjacentHTML are ignored / never upgraded.

Diff with failing tests
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>
Resulting failures screen shot 2017-06-23 at 4 07 17 pm

Invalid syntax in Chrome

These lines cause a syntax error in Chrome 53:

  HTMLElement.prototype = Object.create(origHTMLElement.prototype, {
    constructor, {value: HTMLElement, configurable: true, writable: true}, // THIS LINE
  });

screen shot 2016-09-09 at 8 25 43 am

custom-elements seems to assume that html-imports adds .import to links before it actually does

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.

constructor that populates shadowRoot throws in STP if polyfill is loaded

Repro: http://jsbin.com/jusodew/edit?html,output.

  • This works in Canary, Firefox, and STP with Custom Elements turned off.
  • This fails in STP with Custom Elements turned on, throwing 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.

redundancy in element registration?

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!

Can't define custom element in IE11 - "custom element constructors must be functions" error

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?

Supported version clarification

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"?

Consider including the `native-shim` with the polyfill

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.

Native shim fails to patch Safari intermittently

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.

Steps to reproduce:

  1. npm install -g polymer-cli
  2. mkdir test-app
  3. cd test-app
  4. polymer init (select polymer-2-starter-kit)
  5. polymer build --compile-js
  6. polymer serve build/default
  7. reload in Safari until it throws (may take 20-50 reloads)

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.

`Element#attachShadow` was not patched. redux

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.

Make connected/disconnected synchronous to match spec

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/disconnectedCallbacks synchronous to those methods:

  • appendChild
  • insertBefore
  • removeChild
  • remove
  • replaceChild
  • innerHTML accessor

This 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:

  • some browsers do not implement the 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, and
  • even when you patch instances (which is theoretically possible without much extra code since the CE polyfill takes a look at every node ever created, albeit at some cost), the property descriptor for the native innerHTML 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.

`attributeChangedCallback` is called twice when the attribute is changed

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

Can not call super?

I defined a class for a custom div element like so:

class myAwesomeDiv extends HTMLDivElement{

  constructor(){
    super();
    this.addEventListener('click',e=>this.toggleFav());
  }
 toggleFav(){}
}

and on using it as <awesome-div></awesome-div> ,

I am seeing this (line 82 in app.js is the call to super())
screenshot from 2016-09-09 21-05-29

[question] getting CustomElements to work in a webpack pipeline for older browsers

Hey there,
I'm having some trouble getting this polyfill + native-shim to work right across all devices.

Some background on my setup:

  • Webpack2 + babel-6
  • app is written in ES6, transpiling to ES5
  • imports a node_module written in ES2015, which creates CustomElements used in the app

So 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:

  • I need CustomElement poly loaded before <module that uses CustomElements>
  • I need <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).

  • Transpiling the native-shim to es5 doesn't work
  • using the native-shim as-is at the top of the bundle entry point doesn't work for iOS 8, but does for Chrome
  • not including the native-shim breaks both Chrome and iOS

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"
      ]
    }
  }
}

`setAttribute` converts all attribute names to lowercase before setting

name = name.toLowerCase();

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?

HTML Imports as its own shim

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.

TypeError: Attempting to configurable attribute of unconfigurable property

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.

New Release?

Its been a while and lots of changes occurring - do you have an RC that we can start using?

Improve performance relative to native implementation

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

[Windows] Cannot build with gulp

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.

[v1] consistent constructor

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

Documentation needs correction on IE10 support

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.

Release alpha 4 to NPM

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.

Question: 'Map' is undefined error.

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).

screenshot 2016-11-28 23 56 57

parentNode not updated when element w/ shadowRoot is removed from its parent

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>
  1. we need to wait before we can use attachShadow
  2. after removing el from its parent, el.parentNode is not updated

'native-shim.js' ES6?

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?

Install script shouldn't call bower install

"install": "$(npm bin)/bower install",

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.

'native-shim.js' other native elements?

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.

Polyfill doesn't work if another script patches the DOM

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.

IE11 fails in upgradeElement using Typescript

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

// the super call. See: https://github.com/Microsoft/TypeScript/issues/7574
refers to a typescript issue which has subsequently been closed, but the tests have not been reenabled.

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);

}());

Docs should note that :defined is not supported

May 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.

TypeError: fakeClass is not a constructor

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.