Saturday, February 15, 2014

Polymer and the Native Elements PhantomJS Lacks


The first edition of Patterns in Polymer is due today, leaving me swamped with last minute edits and fixes. But the gods of the chain require their daily sacrifice…

I have very much enjoyed mucking with testing Polymer under Karma and PhantomJS. Testing Polymer with Karma running the tests on Chrome works just fine, but, so far, I have been unable to get the same tests to run on PhantomJS. For the past two days, I have not made much progress getting it working, but the yaks along the way have been useful.

Unfortunately, my stopping point last night suggests that, if it is to work on PhantomJS, some changes will need to be made to Polymer itself. The errors that I had seen in the compressed version of Polymer:
PhantomJS 1.9.7 (Linux) ERROR
        TypeError: 'undefined' is not an object (evaluating 'a.prototype')
        at /home/chris/repos/polymer-book/book/code-js/svg/bower_components/platform/platform.js:29
Turned out to be coming from code in Polymer that wrapped existing elements in polyfilled equivalents. The errors from the uncompressed version of Polymer were along the lines of:
PhantomJS 1.9.7 (Linux) ERROR
        TypeError: 'undefined' is not an object (evaluating 'nativeConstructor.prototype')
        at /home/chris/repos/polymer-book/play/svg/js/scripts/platform/platform.js:1324
That comes from the Polymer platform's register() method for native objects:
        function register(nativeConstructor, wrapperConstructor, opt_instance) {
          // ...
        }
The crux of the problem would appear to be that PhantomJS lacks certain native elements. And, unfortunately, the code in Polymer that tries to use these elements appears extremely procedural. There are a series of anonymous function calls in the Polymer platform that try to wrap the native types that look like:
    (function(scope) {
        "";
        // ...
        var OriginalHTMLImageElement = window.HTMLImageElement;
        // ...
        registerWrapper(OriginalHTMLImageElement, HTMLImageElement, document.createElement("img"));
        // ...
    })(window.ShadowDOMPolyfill);
After manually commenting out this HTMLImageElement wrapper in the platform library (because PhatomJS seems to lack it), I find that I also need to comment out similar code for HTMLMediaElement, HTMLContentElement, and Selection.

That gets me past the original problem. Unfortunately, I find myself dumped into a morass of undefined and null values. At this point, I think it best to call this a dead mine vein. Between some of the seemingly innocuous (at the time) ways in which I shaved yaks previously and the actual hand editing of Polymer code today, I think I am likely too far gone to extract any more useful information from this exercise.

Although ultimately unsuccessful, this expedition was far from a waste of time. I learned much about how Polymer is built and some of the inner workings of the platform. I also got to know PhantomJS a bit better. To be sure, I would have liked to have gotten Karma Polymer tests running on PhantomJS. Maybe I can take another run at this with an alternate approach some day.

For now, it's back to editing. So many typos…


Day #1,027

1 comment:

  1. Man am I glad that I found this. I was about to go crazy testing a Polymer element!

    ReplyDelete