Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IE11 syntax error in custom-elements-es5-adapter #2378

Closed
rictic opened this issue Mar 23, 2017 · 13 comments
Closed

IE11 syntax error in custom-elements-es5-adapter #2378

rictic opened this issue Mar 23, 2017 · 13 comments

Comments

@rictic
Copy link
Contributor

rictic commented Mar 23, 2017

#625 introduces a bug whereby IE11 will throw a syntax error when loading the custom-elements-es5-adapter. This will not cause any other errors, and pages will work fine, there will just be an ominous error reported in the console.

We have a fix for this in mind, but it's somewhat complex and we want to unblock #605 first, as it does break pages.

The fix is for our compiling pipelines to insert some code that will run custom-elements-es5-adapter.js reliably, in a blocking and CSP-compliant manner, if and only if the browser natively supports custom elements. This rules out document.write which Chrome may skip for devices on 2G networks, eval which is not CSP-compliant, and appending the script dynamically using dom methods which does not block. The solution @azakus @FredKSchott and I came up with is to conditionally remove the parent element from the DOM. This means that we also have to move† the script import of the es5 loader into the body if it isn't there already, as no <head>-legal elements can have script children. The desired output looks something like this:

  <div id="ce-es5-shim">
    <script>
      if (!window.customElements) {
        var ceShimContainer = document.querySelector('#ce-es5-shim');
        // This prevents custom-elements-es5-adapter.js from parsing or running.
        ceShimContainer.parentElement.removeChild(ceShimContainer);
      }
    </script>
    <script src="custom-elements-es5-adapter.js"></script>
  </div>
  <script src="webcomponents-loader.js"></script>

† moving a script out of head also means moving all subsequent styles, scripts, and links from the head too, in order to maintain the correct order

@valdrinkoshi
Copy link
Member

valdrinkoshi commented Mar 23, 2017

That's a quite elegant solution! 💯👌
It should be if (!window.customElements) right?

@FredKSchott
Copy link
Contributor

@valdrinkoshi you're right, updating the example...

I'll be building this out for polymer-build & polymer-cli today

@FredKSchott FredKSchott self-assigned this Mar 23, 2017
@usergenic
Copy link
Contributor

If this is in a div in the body, how does this avert the problem when you have a <link rel="import" to a custom element in <head> from executing on Chrome?

@rictic
Copy link
Contributor Author

rictic commented Mar 23, 2017

We have to preserve ordering of links, scripts, and styles, so any of them after the webcomponents-loader.js import will need to be moved too.

@valdrinkoshi
Copy link
Member

the es5 adapter could be injected as the first child of <head>, that should be enough

@usergenic
Copy link
Contributor

@valdrinkoshi (?) but can't <div> in the head...

@rictic
Copy link
Contributor Author

rictic commented Mar 23, 2017

Updated the top comment to mention maintaining ordering

@usergenic
Copy link
Contributor

@FredKSchott There's a lot of specific logic in the Bundler for maintaining ordering after inlining of html import. Let me know if I can be of any help walking through my approach to that.

@valdrinkoshi
Copy link
Member

@usergenic you can http://jsbin.com/yulehe/3/edit?html,console
Tested in IE11, the scripts following the "remover" one are never executed
screen shot 2017-03-23 at 10 50 36 am

@rictic
Copy link
Contributor Author

rictic commented Mar 23, 2017

@valdrinkoshi Look at the elements panel though, <head> is empty

@valdrinkoshi
Copy link
Member

ugh, true ;_; TIL don't mess with <head>

@HendrikThePendric
Copy link

I'm a bit late to the party but solved this problem using the opposite approach, which means I could keep all scripts in the page head:

<script id="custom-elements-es5-adapter-loader">
  if (window.customElements) {
    var src, currTag, script;
    src        = 'bower_components/webcomponentsjs/custom-elements-es5-adapter.js';
    currTag    = document.getElementById('custom-elements-es5-adapter-loader');
    script     = document.createElement('script');
    script.src = src;
    currTag.parentNode.insertBefore(script, currTag.nextSibling);
  }
</script>
<script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script>

Now IE11 will only have the webcomponent-lite, and Chrome will first have the adapter and then the webcomponents-lite.

@oravecz
Copy link

oravecz commented Aug 17, 2017

For me, on Chrome Version 60.0.3112.90 (Official Build) (64-bit) and Version 62.0.3167.0 (Official Build) canary (64-bit), the custom-elements-es5-adapter.js loads after webcomponents-lite.js.

@aomarks aomarks transferred this issue from Polymer/polymer-cli Jan 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants