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

Make the polyfill work in IE & Edge #28

Merged
merged 22 commits into from
Sep 6, 2019

Conversation

Lodin
Copy link
Collaborator

@Lodin Lodin commented Aug 31, 2019

Resolves #12.
Resolves #25.
Fixes #29.

This PR provides support for IE in the polyfill.

@calebdwilliams, sorry for jumping in, I know that you're working on the IE support but you mentioned that you don't have IE11 machine now. So I decided to start working on it in parallel since I have both IE11 and Edge on my machine. Please, feel free to add any solution you prefer.

PR is still in the early stage, a lot of tests are red in IE and Edge now. It may take some time to find a fix all of them.

@calebdwilliams
Copy link
Owner

I think this makes sense if you have immediate access to IE11. As for polyfills, IE supports WeakMap and Map (but not iterable Maps). I would prefer using Rollup to bundle here (or just npm scripts) because the output will be cleaner.

@calebdwilliams
Copy link
Owner

I did also want to say this package should not include its own polyfills for Promise or Map to ensure compatibility with other tools that might be used. Instead please add notes inside the README that note what will be needed.

For example, if I'm running an Angular application, I want the Promise used in this polyfill to be the same one loaded by Angular (or any other framework). I can still be convinced on the Node.isConnected polyfill, but that has less impact on consuming projects.

@Lodin
Copy link
Collaborator Author

Lodin commented Aug 31, 2019

As for polyfills, IE supports WeakMap and Map (but not iterable Maps).

Oh, does it? I thought that it is a ES6 thing for some reason. That's the good news.

I would prefer using Rollup to bundle here (or just npm scripts) because the output will be cleaner.

You mean to transpile the existing code? Well, we can do that but, AFAIK, all polyfills are written with ES5 to make manual tweaks (I did them in the code as well) and get the resulting code size smaller. I personally would prefer to follow this tradition. What do you think about it?

I did also want to say this package should not include its own polyfills for Promise or Map to ensure compatibility with other tools that might be used.

Sure, I completely agree here. Polyfills should not be dependencies, they are the support code that the end user adds if necessary.

I can still be convinced on the Node.isConnected

BTW, I think I found a workaround to not use the polyfill at all. The idea is that if we have ShadowRoot available (I mean, the native ShadowRoot), the browser should definitely support isConnected. And if not, we can just run the simple document.contains check.

@Lodin
Copy link
Collaborator Author

Lodin commented Aug 31, 2019

@calebdwilliams, are you aware how to work with the ShadyCSS? I'm kinda stuck with it. It has its own implementation for adoptedStyleSheets, so all we need to do if it is defined in window is to rely on its API. However, I cannot find any appropriate docs or tutorial on how to use this API. Do you know something?

@calebdwilliams
Copy link
Owner

Really good thought on ShadowRoot and Node.isConnected. I like that approach a lot.

Not sure what you mean here:

You mean to transpile the existing code? Well, we can do that but, AFAIK, all polyfills are written with ES5 to make manual tweaks (I did them in the code as well) and get the resulting code size smaller. I personally would prefer to follow this tradition. What do you think about it?

@Lodin
Copy link
Collaborator Author

Lodin commented Aug 31, 2019

@calebdwilliams, hmm, I'm about your mention of the Rollup. I might mistunderstood you; what did you mean regarding Rollup?

@Lodin Lodin changed the title [WIP] Make the polyfill work in IE [WIP] Make the polyfill work in IE & Edge Aug 31, 2019
@calebdwilliams
Copy link
Owner

So thinking about this a bit, I believe it would be better to keep the src file in ES6+ and Babel down to IE11 support (primarily to keep the code as maintainable as possible). My ideal setup would use Rollup and split out the source into src and maybe divide the code a bit. Then use Babel to output the file in the project’s root. I realize you have done a lot of work on this already, let’s pause though and consider what approach is s most sustainable long term.

@Lodin
Copy link
Collaborator Author

Lodin commented Sep 1, 2019

Well, I don't think that keeping the code in ES5 would be harder than work with it in ES6. I rewrote it, and I don't see much difference. The most visible changes are the following:

  • const/let -> var. Well, that's a mostly cosmetic change.
  • for..of -> forEach. This change should be done in both variants to support IE11 native Map forEach.
  • No destructuring. That's the most painful, probably, but I don't see it as a show-stopper. Now it is wordier, but still quite understandable.
  • No arrow functions. It brings some troubles with this but it is not very popular in the code, so I think I've already fixed every issue.

So, I don't see a lot of disadvantages while there is some advantages:

  • No building system, no additional configuration, the file can be used in any browser with any loading system.
  • While we work with ES5, we understand that there could be some caveats like this one. In ES6 it would be surprising because ES6 is supposed to work with polyfills to fix this type of issues (well, at least I think this way).
  • We can optimize some ES5 code better than Babel would do it. E.g., here I just use the arguments object when Babel inserts for loop to rewrite arguments to an args array. Well, that's not a lot of work nor the bytes, but with the cases above it may play its role.

Plus, as I mentioned above, the polyfills are primarily written in ES5 to be consumed by old browsers directly. I believe we should follow this tradition.

That are my ideas regarding this question. I do not totally disagree with ES6 solution, but while debugging the code in Edge and IE11, I found that it would be way easier to work with ES5 code than a transpiled ES6 (especially it is connected with async-await). That was the reason to rewrite tests to ES5 as well.

@Lodin
Copy link
Collaborator Author

Lodin commented Sep 1, 2019

Ok, from the #30 it looks like that we would need more files to properly support CSSStylesSheet rules. So I agree with ES6 build and Rollup.

@Lodin
Copy link
Collaborator Author

Lodin commented Sep 1, 2019

Hmm, I would say that I'm kinda stuck with the ShadyCSS. I'm not sure it can be properly integrated; all my attempts are like making the polyfill more complicated than it should be.

I'm going to push all changes in the current state, then purge all ShadyCSS-related things and then make PR available. For IE it will work only for the document but not for polyfilled custom elements. Tests will be passed only in Firefox, Chrome, and Safari (or we can disable Custom Element tests for IE & Edge).

So there will be a history of ShadyCSS attempts, and if someone can make it work, it would be great.

@Lodin
Copy link
Collaborator Author

Lodin commented Sep 1, 2019

By the way, I'm not sure we should try to integrate it since ShadyCSS has its own implementation already. Support of adopted style sheets in shadow roots is tightly coupled with supporting web components, and polyfilling web components is definitely out of scope for this project.

* Split code to separate files
* Add Rollup build with detection injection
* Attempt to work together with ShadyCSS
@codecov-io
Copy link

codecov-io commented Sep 2, 2019

Codecov Report

Merging #28 into master will increase coverage by 0.17%.
The diff coverage is 95.59%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #28      +/-   ##
==========================================
+ Coverage   95.42%   95.59%   +0.17%     
==========================================
  Files           1        7       +6     
  Lines         153      159       +6     
==========================================
+ Hits          146      152       +6     
  Misses          7        7
Impacted Files Coverage Δ
src/observer.js 100% <100%> (ø)
src/utils.js 100% <100%> (ø)
src/shared.js 100% <100%> (ø)
src/index.js 83.33% <83.33%> (ø)
src/init.js 93.1% <93.1%> (ø)
src/ConstructStyleSheet.js 93.47% <93.47%> (ø)
src/adopt.js 97.5% <97.5%> (ø)
... and 4 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5c6a1d8...52cc5c7. Read the comment docs.

@Lodin
Copy link
Collaborator Author

Lodin commented Sep 2, 2019

Hmm, the version of Firefox and Chrome in travis is rather old (56 when the current is 68), it might be a reason why tests fail. I have all of them passing on my local Firefox 68.

@Lodin Lodin marked this pull request as ready for review September 2, 2019 07:52
@Lodin Lodin changed the title [WIP] Make the polyfill work in IE & Edge Make the polyfill work in IE & Edge Sep 2, 2019
@calebdwilliams
Copy link
Owner

Sorry I've been out of the pocket over the weekend, it was a holiday here in the US yesterday, but I'm back online. Can you get some info about why the tests are failing? I'll see if I can't figure out how to upgrade Firefox in Travis (or if that's even possible).

@Lodin
Copy link
Collaborator Author

Lodin commented Sep 3, 2019

@calebdwilliams, probably, it does not support Web Components. AFAIK, Firefox supports them starting from the version 63 (October of 2018) while Travis suggests version 56.

I really don't understand why it does provide such old browsers. My project runs on the Chrome 76, and my .travis.yml file does not have much difference from yours. The only big difference I can see is that your project runs on https://travis-ci.com (the new one) and my - on the https://travis-ci.org (the old one). But I don't see any particular reason to load such different versions.

However, let's try setting Firefox from stable to latest (I've seen it in the Travis docs)

@Lodin
Copy link
Collaborator Author

Lodin commented Sep 3, 2019

By the way, what do you think about my suggestion of not supporting ShadyCSS at all since it has its own support? We would be able to support only the document level of adoptedStyleSheet and it may play fine with ShadyCSS implementation of Constructible Style Sheets.

@calebdwilliams
Copy link
Owner

calebdwilliams commented Sep 3, 2019

Let's put ShadyCSS support on the back burner for now. That might be something to revisit in the future, but that is tangential to the primary goal of this PR.

As for Firefox, please feel free to update the Travis config. I saw both versions listed on the Travis documentation, so it could have been a mis-type somewhere.

Edit

FWIW, let's remove any attempt to get ShadyCSS working (maybe create a new branch to retain what you currently have so we can revisit later). Before this update is ready, I'd like these commits to be squashed, too.

@Lodin
Copy link
Collaborator Author

Lodin commented Sep 3, 2019

I already purged all attempts to get ShadyCSS working.

Before this update is ready, I'd like these commits to be squashed, too.

Maybe, it would be better to squash the whole PR? You can do it via the Github interface:

@Lodin
Copy link
Collaborator Author

Lodin commented Sep 3, 2019

Ok, looks like it works :) Tests are passed

@Lodin
Copy link
Collaborator Author

Lodin commented Sep 3, 2019

Oh wait, one more thing to remove

@Lodin
Copy link
Collaborator Author

Lodin commented Sep 3, 2019

Ok, this PR is ready, let's squash it and merge 🙂

Copy link
Owner

@calebdwilliams calebdwilliams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't had time to give this a thorough look through just yet, but I do have a couple initial questions/feedback.

README.md Show resolved Hide resolved
karma.conf.js Outdated Show resolved Hide resolved
scripts/build.js Show resolved Hide resolved
@calebdwilliams
Copy link
Owner

calebdwilliams commented Sep 4, 2019

I was also thinking Element.insertAdjacentElement with 'afterbegin' might be a better solution for our Element.append workaround.

@Lodin
Copy link
Collaborator Author

Lodin commented Sep 4, 2019

Unfortunately, Element.insertAdjacentElement works only with objects that implement Element interface, not the Node. So, we cannot use it with the DocumentFragment. I don't know why it is designed this way, such a disappointment.

Copy link
Owner

@calebdwilliams calebdwilliams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really minor comments. Also add the instanceof language to README so the limitation in IE11 is documented. Once those last few things are ready I'll squash and merge.

test/_index.html Outdated
@@ -5,6 +5,6 @@
<body>
<h1>Hello world</h1>
</body>
<script src="../adoptedStyleSheets.js"></script>
<script type="module" src="../src/index.js"></script>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to load from dist or set up a script to run this from localhost otherwise this doesn't work from file://

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, I forgot about this part.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, it's still [type=module] which won't load from file://

test/index.html Outdated
@@ -3,12 +3,12 @@
<head>
<title>Constructed style sheets test</title>
<meta charset="UTF-8">
<script src="../adoptedStyleSheets.js"></script>
<script src="../src/index.js" type="module"></script>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to load from dist or set up a script to run this from localhost otherwise this doesn't work from file://

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

test/_index.html Outdated
@@ -5,6 +5,6 @@
<body>
<h1>Hello world</h1>
</body>
<script src="../adoptedStyleSheets.js"></script>
<script type="module" src="../src/index.js"></script>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, it's still [type=module] which won't load from file://

README.md Outdated
required.

For browsers that do not support the web components specification (currently
IE 11 and Edge) only the document-level style sheets adoption works.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And checking instanceof will not work in IE11 due to Symbol not being natively supported.

Copy link
Collaborator Author

@Lodin Lodin Sep 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I am sure that I fixed it and the previous one. It looks the following now:

<script src="../dist/adoptedStyleSheets.js"></script>

and

## Support
This polyfill supports all modern browsers and IE 11.

For browsers that do not support the web components specification (currently
IE 11 and Edge) only the document-level style sheets adoption works.

### IE 11

To make this polyfill work with IE 11 you need the following tools:
- `Symbol` polyfill (with support for `Symbol.hasInstance`).
- [@babel/plugin-transform-instanceof](https://www.npmjs.com/package/@babel/plugin-transform-instanceof)
applied to your code that uses `instanceof` against `CSSStyleSheet`.

Copy link
Owner

@calebdwilliams calebdwilliams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@calebdwilliams calebdwilliams merged commit d47264b into calebdwilliams:master Sep 6, 2019
@pika-ci
Copy link

pika-ci bot commented Sep 6, 2019

🚀 This PR has been merged! Once a new release is created, any changes will become available on npm. Until then, you can load and install it directly from the Pika CDN:

npm install https://cdn.pika.dev/construct-style-sheets-polyfill/master
import * as pkg from 'https://cdn.pika.dev/construct-style-sheets-polyfill/master';

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Edge bug Find alternative to isConnected IE11 Support
3 participants