paper-input icon indicating copy to clipboard operation
paper-input copied to clipboard

WKWebView issue when creating the paper-textarea element from document.createElement()

Open BorntraegerMarc opened this issue 6 years ago • 5 comments

Description

Our app gets called in two separate ways:

  1. Like a normal web page through Google chrome
  2. Through our native iOS app with WkWebView

So our approach was to build only a native app for iOS to fill the gaps of the ServiceWorker (like to enable push notifications, offline support, etc.). Which Safari, obviously doesn't have but chrome does.

On Google chrome (all versions) the app works without issues. And on our Safari native app the web app crashes. Total crash happens without error message. So screen just gets blank.

We are using Angular and Polymer together. So this is why this issue came up -> it only happens if a web component is created via document.createElement(). So programmatically. Which Angular always does.

This is the browser version of WkWebView (verified with http://www.whoishostingthis.com/tools/user-agent/): Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_2 like Mac OS X) AppleWebKit/603.2.4 (KHTML, like Gecko) Mobile/14F89

This is how we instantiate the paper-textarea:

<paper-textarea label="test" id="newMessage" name="newMessage"></paper-textarea>

The issue is only with paper-textarea. paper-input works perfectly

Expected outcome

The app get's loaded correctly over WKWebView. Maybe there is something that paper-textarea does, which messes up the loading on WKWebView.

Actual outcome

The Problem

Adding the to index.html was fine, but the Angular DefaultDomRenderer2 could not create it without throwing the error "A newly constructed custom element must not have attributes".

This is the cause for things breaking. While document.createElement() lets you continue, the element it returns is actually an HTMLUnknownElement, and so naturally it doesn't open its Shadow DOM from extending Polymer.Element.

Raw vs Programmatic Element Creation

There are two ways to "create" an element: raw HTML and programatically. A Polymer project goes through raw HTML. It provides it directly to the browser to render.

Angular does things programmatically and calls document.createElement(). This is why you can do weird things like <paper-item class$="[[binding]]"> in Polymer but not Angular. class$ is not a valid attribute and throws an error when calling element.setAttribute('class$', '[[binding]]').

Not Just Angular!

So far, all the tests have just been isolated on <paper-textarea>. I'm testing with both this element and <paper-input>, since they're similar. <paper-input> is perfectly chill with document.createElement().

I've ruled out Origami as the problem, so I thought maybe something with zone.js or the reflect shim was adding attributes at element creation. I decided to turn to pure Polymer and take both of these and any other weird Angular shenanigans out of the picture.

https://raw-dot-custom-elements.appspot.com/PolymerElements/paper-input/v2.0.0/paper-input/demo/index.html

This is the demo file that we should navigate to within the WKWebView. It'll load up just fine and <paper-textarea> works. Inspect the console and run the following:

window.onerror = function(err) { debugger; console.log('error', err) };
var ele = document.createElement('paper-textarea');
console.log(ele instanceof HTMLUnknownElement);
console.log(ele instanceof customElements.get('paper-textarea'));

Output:

[Log] error – "NotSupportedError (DOM Exception 9): A newly constructed custom element must not have attributes"
[Error] NotSupportedError (DOM Exception 9): A newly constructed custom element must not have attributes
	createElement
	Console Evaluation (Console Evaluation 4:3)
	evaluateWithScopeExtension
	_evaluateOn
	_evaluateAndWrap
	evaluate
[Log] true
[Log] false

Thoughts

When creating a small component such as:

<dom-module id="paper-wrapped">
  <template>
    <paper-textarea value="{{value}}"></paper-textarea>
  </template>
  <script>
    Polymer({
      is: 'paper-wrapped',
      properties: {
        value: {
          type: String,
          notify: true      
       }
      }
    });
  </script>
</dom-module>

The whole concept works without problems. The website can be called via WKWebView.

We have ruled out the problem with the word "textarea". We thought maybe WKWebView sees that and is adding some textarea-specific attributes when it shouldn't be. But we tried it with this repo: https://github.com/BorntraegerMarc/paper-input which did not work as well.

Live Demo

  • https://github.com/kmyllyvi/WKWebViewTester
  • https://github.com/BorntraegerMarc/polymer-chat
  • https://raw-dot-custom-elements.appspot.com/PolymerElements/paper-input/v2.0.0/paper-input/demo/index.html

Steps to reproduce

We ran the following tests:

  1. We generated a normal polymer project with Polymer starter kit and everything worked as excpected. So the error only comes up if angular (or origami) is included
  2. We created this minimal origami project: https://github.com/BorntraegerMarc/polymer-chat and the WKWebView crashes at the exact same component. Because of this: https://github.com/BorntraegerMarc/polymer-chat/blob/master/src/app/message/input/message-input.component.html#L3
  3. If you completely comment out the paper-textarea component from the HTML it works without issue. So the TS reference @ViewChild('messageInput') has no influence on it. when we commented out @ViewChild the same issue persisted. Ony when commenting out the HTML code the app started to work again.

For easy testing purposes we created the following iOS native app project: https://github.com/kmyllyvi/WKWebViewTester you can just clone & run it. Which is just a WKWebView project. How to test:

  1. Clone and install the minimal origami project
  2. Clone and install the WKWebView project
  3. Start angular with ng serve
  4. Start the ios app project on an iPhone simulator and navigate to http://localhost:3000 (you can enter the URL in the actual app)

Browsers Affected

  • [ ] Chrome
  • [ ] Firefox
  • [X] WKWebView on all safari versions
  • [ ] Safari 9
  • [ ] Safari 8
  • [ ] Safari 7
  • [ ] Edge
  • [ ] IE 11
  • [ ] IE 10

BorntraegerMarc avatar Jul 18 '17 15:07 BorntraegerMarc