From b3727b3cc08225e27a2f72105d6ea495ff975661 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Thu, 11 Jul 2013 14:29:18 -0700 Subject: [PATCH 01/29] remove build log --- build.log | 41 ----------------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 build.log diff --git a/build.log b/build.log deleted file mode 100644 index f0ae67d66b..0000000000 --- a/build.log +++ /dev/null @@ -1,41 +0,0 @@ -BUILD LOG ---------- -Build Time: 2013-06-17T12:21:13 - -NODEJS INFORMATION -================== -nodejs: v0.10.4 -chai: 1.6.1 -grunt: 0.4.1 -grunt-audit: 0.0.0 -grunt-contrib-uglify: 0.2.2 -grunt-contrib-yuidoc: 0.4.0 -grunt-karma-0.9.1: 0.4.3 -karma: 0.9.2 -karma-chrome-launcher: 0.0.1 -karma-coffee-preprocessor: 0.0.1 -karma-crbot-reporter: 0.0.3 -karma-firefox-launcher: 0.0.2 -karma-jasmine: 0.0.1 -karma-mocha: 0.0.1 -karma-phantomjs-launcher: 0.0.2 -karma-requirejs: 0.0.1 -karma-script-launcher: 0.0.1 -mocha: 1.10.0 - -REPO REVISIONS -============== -polymer: 24689e70b7ebb122909d4ed17b53a2b2a455a2e5 -platform: 569a80ae565a0ecbe01d3a79128021fdf1caaff7 -ShadowDOM: 7a50b20542a559a0ffccb9e3a9330246a1f9fb5f -HTMLImports: 7960a892cd4461333809605c3806ba4da699b1f0 -CustomElements: 76bfa07e8bfd5ed75c0c14682a66c40600e6baa0 -PointerEvents: 9bab6b80e74fcbbdb4145286aae264ae54175419 -PointerGestures: d6328b1e65daf111720f76b70f6d469a91a96335 -mdv: aaa18dc0069764ec9f25654c949e4a1071f551f2 - -BUILD HASHES -============ -polymer.min.js: 434cd0b3e8d81699760c75043ab6f7c5676db006 -polymer.native.min.js: 4f966c0f59a909dd3ac28068f1164016551ec179 -polymer.sandbox.min.js: 7444aba9341f62aeb0d89538ee033c77c16cd0e0 \ No newline at end of file From 448c4d7ba30fd1727cd10c8f1531c56bfc7ac495 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Tue, 16 Jul 2013 06:16:06 -0700 Subject: [PATCH 02/29] Throw a useful error for deprecated use of Polymer.register Fixes #210 --- gruntfile.js | 3 ++- polymer.js | 3 ++- src/deprecated.js | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/deprecated.js diff --git a/gruntfile.js b/gruntfile.js index 128482886e..9df167fdfe 100644 --- a/gruntfile.js +++ b/gruntfile.js @@ -38,7 +38,8 @@ module.exports = function(grunt) { "declaration/events.js", "declaration/properties.js", "declaration/attributes.js", - "declaration/polymer-element.js" + "declaration/polymer-element.js", + "deprecated.js" ].map(function(n) { return "src/" + n; }); diff --git a/polymer.js b/polymer.js index 1e77e26c95..864d63ac94 100644 --- a/polymer.js +++ b/polymer.js @@ -31,7 +31,8 @@ var modules = [ "declaration/events.js", "declaration/properties.js", "declaration/attributes.js", - "declaration/polymer-element.js" + "declaration/polymer-element.js", + "deprecated.js" ].map(function(n) { return "src/" + n; })); diff --git a/src/deprecated.js b/src/deprecated.js new file mode 100644 index 0000000000..e543b2b475 --- /dev/null +++ b/src/deprecated.js @@ -0,0 +1,14 @@ +/* + * Copyright 2013 The Polymer Authors. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +// NOTE: put deprecated methods here that throw a useful error +Polymer.register = function(context) { + if (context != window) { + // context is the here, with a name attribute + var name = context.getAttribute('name'); + throw new Error('Polymer.register is deprecated in declaration of ' + name + '. Please see http://www.polymer-project.org/getting-started.html'); + } +}; From 9a0879f07d0c238a787db1db81550293d8868dbf Mon Sep 17 00:00:00 2001 From: "Scott J. Miles" Date: Wed, 17 Jul 2013 12:38:11 -0700 Subject: [PATCH 03/29] native `createdCallback` fires immediately on element creation, before children are processed, so - + diff --git a/test/html/publish-attributes.html b/test/html/publish-attributes.html index c38f055dbd..1c98289c93 100644 --- a/test/html/publish-attributes.html +++ b/test/html/publish-attributes.html @@ -8,16 +8,10 @@ - - + - - + diff --git a/test/html/unbind.html b/test/html/unbind.html index c5a019d8d0..fd79d9db09 100644 --- a/test/html/unbind.html +++ b/test/html/unbind.html @@ -61,11 +61,11 @@ return [document.createElement('x-test')]; }, function(node) { - chai.assert.isTrue(node._unbound, - 'element is unbound when not inserted'); + chai.assert.isUndefined(node._unbound, + 'element is bound when not inserted'); node.foo = 'bar'; Platform.flush(); - chai.assert.isUndefined(node.fooWasChanged, 'node is actually unbound'); + chai.assert.isTrue(node.fooWasChanged, 'node is actually bound'); var n = document.createElement('x-test'); n.cancelUnbindAll(); return [n]; From 16266cbb9a4a4a70cce1cec1d3fdacc972d35ae1 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Tue, 23 Jul 2013 09:59:51 -0700 Subject: [PATCH 07/29] Add 'noscript' to instance attributes black list. --- src/declaration/attributes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declaration/attributes.js b/src/declaration/attributes.js index 667d95cef7..d773d5501d 100644 --- a/src/declaration/attributes.js +++ b/src/declaration/attributes.js @@ -89,7 +89,7 @@ isInstanceAttribute: function(name) { return !this.blackList[name] && name.slice(0,3) !== 'on-'; }, - blackList: {name: 1, 'extends': 1, constructor: 1} + blackList: {name: 1, 'extends': 1, constructor: 1, noscript: 1} }; // add ATTRIBUTES symbol to blacklist From f50c6f80b75ae25e0fc83a4635ba98308e9b5695 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Wed, 24 Jul 2013 10:28:37 -0700 Subject: [PATCH 08/29] Allow a prototypal value of null to indicate that a property should be deserialized as an object. Addresses issue #215 --- src/lib/deserialize.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/lib/deserialize.js b/src/lib/deserialize.js index db03c1577a..84f4f398f7 100644 --- a/src/lib/deserialize.js +++ b/src/lib/deserialize.js @@ -24,9 +24,6 @@ return (String(floatVal) === value) ? floatVal : value; }, 'object': function(value, defaultValue) { - if (!defaultValue) { - return value; - } try { // If the string is an object, we can parse is with the JSON library. // include convenience replace for single-quotes. If the author omits From 318a26011c3f001463bad7f2864cd4a88a4cc909 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Wed, 24 Jul 2013 10:35:15 -0700 Subject: [PATCH 09/29] Addresses issue #188: - attributes are now reflected to property values at runtime, not only at create time. The rules are the same, the attribute is deserialized to the data type of the property in the element's prototype. - `published` properties are now reflected to attributes at runtime. This is done via observation and all published properties are now observed. Properties are serialized directly to strings and object and undefined valued properties are ignored. --- polymer.js | 2 +- src/instance/attributes.js | 13 ++++++ src/instance/base.js | 3 +- src/instance/properties.js | 7 ++- test/html/prop-attr-reflection.html | 70 +++++++++++++++++++++++++++++ test/js/attrs.js | 1 + 6 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 test/html/prop-attr-reflection.html diff --git a/polymer.js b/polymer.js index 864d63ac94..3f8574ff47 100644 --- a/polymer.js +++ b/polymer.js @@ -21,8 +21,8 @@ var modules = [ "api.js", "instance/utils.js", "instance/events.js", - "instance/properties.js", "instance/attributes.js", + "instance/properties.js", "instance/mdv.js", "instance/base.js", "instance/styles.js", diff --git a/src/instance/attributes.js b/src/instance/attributes.js index 47519df37b..57bee66eda 100644 --- a/src/instance/attributes.js +++ b/src/instance/attributes.js @@ -61,6 +61,19 @@ // convert representation of 'stringValue' based on type of 'defaultValue' deserializeValue: function(stringValue, defaultValue) { return scope.deserializeValue(stringValue, defaultValue); + }, + serializeValue: function(value) { + if (typeof value != 'object' && value !== undefined) { + return value; + } + }, + propertyToAttribute: function(name) { + if (Object.keys(this[PUBLISHED]).indexOf(name) >= 0) { + var serializedValue = this.serializeValue(this[name]); + if (serializedValue !== undefined) { + this.setAttribute(name, serializedValue); + } + } } }; diff --git a/src/instance/base.js b/src/instance/base.js index aa9635b638..7fbbf38ec7 100644 --- a/src/instance/base.js +++ b/src/instance/base.js @@ -100,7 +100,8 @@ }; } }, - attributeChangedCallback: function() { + attributeChangedCallback: function(name, oldValue) { + this.attributeToProperty(name, this.getAttribute(name)); if (this.attributeChanged) { this.attributeChanged.apply(this, arguments); } diff --git a/src/instance/properties.js b/src/instance/properties.js index 244cf26203..7c2c7d59c8 100644 --- a/src/instance/properties.js +++ b/src/instance/properties.js @@ -12,6 +12,8 @@ // magic words var OBSERVE_SUFFIX = 'Changed'; + + var PUBLISHED = scope.api.instance.attributes.PUBLISHED; // element api @@ -53,10 +55,13 @@ unregisterObservers(this); }, // property should be observed if it has an observation callback + // or if it is published shouldObserveProperty: function(name) { - return Boolean(this[name + OBSERVE_SUFFIX]); + return Boolean(this[name + OBSERVE_SUFFIX] || + Object.keys(this[PUBLISHED]).indexOf(name) >= 0); }, dispatchPropertyChange: function(name, oldValue) { + this.propertyToAttribute(name); invoke.call(this, name + OBSERVE_SUFFIX, [oldValue]); } }; diff --git a/test/html/prop-attr-reflection.html b/test/html/prop-attr-reflection.html new file mode 100644 index 0000000000..1404f2cfac --- /dev/null +++ b/test/html/prop-attr-reflection.html @@ -0,0 +1,70 @@ + + + + publish attributes + + + + + + + + + + + + + + + + + diff --git a/test/js/attrs.js b/test/js/attrs.js index 06191d0174..e0271f8bc2 100644 --- a/test/js/attrs.js +++ b/test/js/attrs.js @@ -8,4 +8,5 @@ htmlSuite('attributes-declarative', function() { htmlTest('html/publish-attributes.html'); htmlTest('html/take-attributes.html'); htmlTest('html/attr-mustache.html'); + htmlTest('html/prop-attr-reflection.html'); }); \ No newline at end of file From bbd887b676225780b637bffb217a7c584611c5df Mon Sep 17 00:00:00 2001 From: "Scott J. Miles" Date: Wed, 24 Jul 2013 11:23:55 -0700 Subject: [PATCH 10/29] document blacklist (a bit) --- src/declaration/attributes.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/declaration/attributes.js b/src/declaration/attributes.js index d773d5501d..1c8e66d5a0 100644 --- a/src/declaration/attributes.js +++ b/src/declaration/attributes.js @@ -89,6 +89,7 @@ isInstanceAttribute: function(name) { return !this.blackList[name] && name.slice(0,3) !== 'on-'; }, + // do not clone these attributes onto instances blackList: {name: 1, 'extends': 1, constructor: 1, noscript: 1} }; From 20c622c553f8fbd2eff567c73c65c24d49e3d89c Mon Sep 17 00:00:00 2001 From: "Scott J. Miles" Date: Sat, 27 Jul 2013 16:45:12 -0700 Subject: [PATCH 11/29] fix grunt file --- build.bat | 5 +++++ gruntfile.js | 7 +++---- 2 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 build.bat diff --git a/build.bat b/build.bat new file mode 100644 index 0000000000..066f9965a5 --- /dev/null +++ b/build.bat @@ -0,0 +1,5 @@ +@ECHO NPM INSTALL +@call npm install +@ECHO . +@ECHO GRUNT +@call grunt \ No newline at end of file diff --git a/gruntfile.js b/gruntfile.js index 9df167fdfe..1b102435b3 100644 --- a/gruntfile.js +++ b/gruntfile.js @@ -19,17 +19,16 @@ module.exports = function(grunt) { Polymer = [ "polymer.js", "boot.js", - "shimStyling.js", "lib/lang.js", - "lib/dom.js", - "lib/deserialize.js", "lib/job.js", + "lib/dom.js", "lib/super.js", + "lib/deserialize.js", "api.js", "instance/utils.js", "instance/events.js", - "instance/properties.js", "instance/attributes.js", + "instance/properties.js", "instance/mdv.js", "instance/base.js", "instance/styles.js", From dcce1d4efc753b7a213d79cfb3d3b578dc32dfeb Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Mon, 29 Jul 2013 11:32:44 -0700 Subject: [PATCH 12/29] repair references in test: < shadow >.olderShadowRoot removed in favor of shadowRoot.olderShadowRoot --- test/html/event-path.html | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/html/event-path.html b/test/html/event-path.html index c28456b04b..8ab12e9786 100644 --- a/test/html/event-path.html +++ b/test/html/event-path.html @@ -71,19 +71,18 @@ menuButton.$.menuButtonContent, menu.$.selectorContent, menu.$.selectorDiv, - menu.$.menuShadow.olderShadowRoot, + menu.shadowRoot.olderShadowRoot, menu.$.menuShadow, menu.$.menuDiv, - menu.webkitShadowRoot, + menu.shadowRoot, menu, menuButton.$.menuButtonDiv, menuButton.$.overlay.$.overlayContent, - menuButton.$.overlay.webkitShadowRoot, + menuButton.$.overlay.shadowRoot, menuButton.$.overlay, - menuButton.webkitShadowRoot, + menuButton.shadowRoot, menuButton ]; -console.log(path) var x = 0; path.forEach(function(n, i) { n.addEventListener('x', function(e) { From e4dd36f14065c29bc49128532d4c05fc406a3670 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Mon, 29 Jul 2013 11:33:13 -0700 Subject: [PATCH 13/29] make test pass in the presence of ShadowDOMPolyfill since these features are not polyfilled. --- test/html/styling/apply-reset-styles.html | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/html/styling/apply-reset-styles.html b/test/html/styling/apply-reset-styles.html index 1e60a5d07e..aea8ce69f3 100644 --- a/test/html/styling/apply-reset-styles.html +++ b/test/html/styling/apply-reset-styles.html @@ -39,6 +39,11 @@ diff --git a/test/js/events.js b/test/js/events.js index 1a6bae705d..ceb3a4ebbd 100644 --- a/test/js/events.js +++ b/test/js/events.js @@ -33,13 +33,15 @@ suite('events', function() { test('host event', function(done) { createTestElement('x-foo'); + // Ensure IE goes... + CustomElements.takeRecords(); setTimeout(function() { var foo = document.createElement('x-foo'); work.appendChild(foo); foo.click(); assert.equal(results.textContent, 'x-foo'); done(); - }, 100); + }, 0); }); /*test('host events order', function() { diff --git a/test/js/register.js b/test/js/register.js index c8752f8fee..93a1e39d81 100644 --- a/test/js/register.js +++ b/test/js/register.js @@ -28,6 +28,8 @@ suite('register', function() { } }); work.innerHTML = ''; + // Ensure IE goes... + CustomElements.takeRecords(); setTimeout(function() { var foo = document.createElement('x-foo'); // test ready @@ -36,7 +38,7 @@ suite('register', function() { foo.sayHello(); assert.equal(foo.message, 'hello'); done(); - }, 100); + }, 0); }); }); From d40dc98d0cd7f14016af27dd7b1c202062817ef0 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Mon, 29 Jul 2013 18:05:02 -0700 Subject: [PATCH 16/29] super requires __proto__. Simulate this in *test* where unsupported. --- test/js/oop.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/js/oop.js b/test/js/oop.js index 745728c4b3..2e8a2df61f 100644 --- a/test/js/oop.js +++ b/test/js/oop.js @@ -4,6 +4,16 @@ * license that can be found in the LICENSE file. */ +function createObjectWithProto(prototype) { + var obj = Object.create(prototype); + // NOTE: On some platforms (IE10) __proto__ does not exist. + // In this case, we install it. + if (!Object.__proto__) { + obj.__proto__ = prototype; + } + return obj; + } + suite('oop', function() { var assert = chai.assert; @@ -21,7 +31,7 @@ suite('oop', function() { }; // var Sub = function() {}; - Sub.prototype = Object.create(Base.prototype); + Sub.prototype = createObjectWithProto(Base.prototype); Sub.prototype.say = function() { this.super(); this.log(' sub'); @@ -29,7 +39,7 @@ suite('oop', function() { Sub.prototype.say.nom = 'say'; // var SubSub = function() {}; - SubSub.prototype = Object.create(Sub.prototype); + SubSub.prototype = createObjectWithProto(Sub.prototype); SubSub.prototype.say = function() { this.super(); this.log(' subsub'); From 5ab7b2f92a9dcee05316e222304b587570c4a650 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Mon, 29 Jul 2013 18:05:29 -0700 Subject: [PATCH 17/29] Temporarily remove failing mdv syntax test, blocked on https://github.com/Polymer/ShadowDOM/issues/189 --- test/js/mdv-syntax.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/js/mdv-syntax.js b/test/js/mdv-syntax.js index daf6c72c52..03c6a56b8b 100644 --- a/test/js/mdv-syntax.js +++ b/test/js/mdv-syntax.js @@ -5,6 +5,11 @@ */ htmlSuite('MDV syntax', function() { - htmlTest('html/mdv-syntax.html'); - htmlTest('html/mdv-syntax.html?shadow'); + // TODO(sorvell): only test under native until the following + // ShadowDOMPolyfill issue is addressed: + // https://github.com/Polymer/ShadowDOM/issues/189 + if (!window.ShadowDOMPolyfill) { + htmlTest('html/mdv-syntax.html'); + } + //htmlTest('html/mdv-syntax.html?shadow'); }); From 62eb34b53c9192b3378c4896cb353087cbecadd8 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Mon, 29 Jul 2013 18:13:06 -0700 Subject: [PATCH 18/29] Improve IE compatibility by ensuring the __proto__ chain always exists. In conjunction with https://github.com/Polymer/CustomElements/commit/9b4c5df1c34c9401075fbca602064d7552f3d079, helps address https://github.com/Polymer/polymer/issues/217. --- src/declaration/polymer-element.js | 9 ++++++--- src/lib/super.js | 11 +++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/declaration/polymer-element.js b/src/declaration/polymer-element.js index dcd5c46c22..cdd4b75b9f 100644 --- a/src/declaration/polymer-element.js +++ b/src/declaration/polymer-element.js @@ -66,14 +66,17 @@ // Potentially remove when spec bug is addressed. // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21407 this.addResolvePathApi(); - // declarative features - this.desugar(); // under ShadowDOMPolyfill, transforms to approximate missing CSS features if (window.ShadowDOMPolyfill) { Platform.ShadowCSS.shimStyling(this.templateContent(), name, extnds); } // register our custom element this.register(name); + // declarative features + // NOTE: make sure to desugar after calling register. Registration + // ensures the __proto__ chain exists on platforms that don't support it + // natively (IE10), and desugar uses the __proto__ chain. + this.desugar(); // reference constructor in a global named by 'constructor' attribute this.publishConstructor(); }, @@ -132,7 +135,7 @@ // make a fresh object that inherits from a prototype object inheritObject: function(prototype, name) { // copy inherited properties onto a new object - prototype[name] = extend({}, prototype.__proto__[name]); + prototype[name] = extend({}, Object.getPrototypeOf(prototype)[name]); }, // register 'prototype' to custom element 'name', store constructor register: function(name) { diff --git a/src/lib/super.js b/src/lib/super.js index 398eb77d64..d24bb5a26f 100644 --- a/src/lib/super.js +++ b/src/lib/super.js @@ -38,7 +38,7 @@ } // super prototype is either cached or we have to find it // by searching __proto__ (at the 'top') - memoizeSuper(caller, nom, Object.getPrototypeOf(this)); + memoizeSuper(caller, nom, getPrototypeOf(this)); } var _super = caller._super; if (!_super) { @@ -61,7 +61,7 @@ // look for an inherited prototype that implements name while (proto && (!proto.hasOwnProperty(name) || proto[name] === caller)) { - proto = Object.getPrototypeOf(proto); + proto = getPrototypeOf(proto); } return proto; }; @@ -93,6 +93,13 @@ p = p.__proto__; } } + + // NOTE: In some platforms (IE10) the prototype chain is faked via + // __proto__. Therefore, always get prototype via __proto__ instead of + // the more standard Object.getPrototypeOf. + function getPrototypeOf(prototype) { + return prototype.__proto__; + } // exports From 7bcf366529c20cd07bd9467044cd277dcd3d631b Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Mon, 29 Jul 2013 21:06:56 -0700 Subject: [PATCH 19/29] Remove deprecated files. --- src/lib/styles.js | 209 -------------------- src/shimStyling.js | 462 --------------------------------------------- 2 files changed, 671 deletions(-) delete mode 100644 src/lib/styles.js delete mode 100644 src/shimStyling.js diff --git a/src/lib/styles.js b/src/lib/styles.js deleted file mode 100644 index 91ca7ba15d..0000000000 --- a/src/lib/styles.js +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2013 The Polymer Authors. All rights reserved. - * Use of this source code is governed by a BSD-style - * license that can be found in the LICENSE file. - */ -(function(scope) { - - var STYLE_SELECTOR = 'style'; - var SHEET_SELECTOR = '[rel=stylesheet]'; - var STYLE_SCOPE_ATTRIBUTE = 'element'; - var STYLE_GLOBAL_SCOPE = 'global'; - var STYLE_CONTROLLER_SCOPE = 'controller'; - var SCOPE_ATTR = 'polymer-scope'; - - // imports - - var log = window.logFlags || {}; - - var styles = { - /** - * Install external stylesheets loaded in elements into the - * element's template. - * @param elementElement The element to style. - */ - installSheets: function(elementElement) { - installLocalSheets(elementElement); - installGlobalStyles(elementElement); - }, - /** - * Takes external stylesheets loaded in an element and moves - * their content into a - - - could become: - - -
- -
- - Note the use of @polyfill in the comment above a ShadowDOM specific style - declaration. This is a directive to the styling shim to use the selector - in comments in lieu of the next selector when running under polyfill. -*/ -(function(scope) { - -var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); -var concat = Array.prototype.concat.call.bind(Array.prototype.concat); -var slice = Array.prototype.slice.call.bind(Array.prototype.slice); - -var stylizer = { - hostRuleRe: /@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim, - selectorRe: /([^{]*)({[\s\S]*?})/gim, - hostElementRe: /(.*)((?:\*)|(?:\:scope))(.*)/, - hostFixableRe: /^[.\[:]/, - cssCommentRe: /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, - cssPolyfillCommentRe: /\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim, - cssPseudoRe: /::(x-[^\s{,(]*)/gim, - selectorReSuffix: '([>\\s~+\[.,{:][\\s\\S]*)?$', - hostRe: /@host/gim, - cache: {}, - shimStyling: function(element) { - if (window.ShadowDOMPolyfill && element) { - // use caching to make working with styles nodes easier and to facilitate - // lookup of extendee - var name = element.getAttribute('name'); - stylizer.cacheDefinition(element); - stylizer.shimPolyfillDirectives(element.styles, name); - // find styles and apply shimming... - if (Polymer.strictPolyfillStyling) { - stylizer.applyScopeToContent(element.templateContent(), name); - } - stylizer.applyShimming(stylizer.stylesForElement(element), name); - } - }, - // Shim styles to be placed inside a shadowRoot. - // 1. shim @host rules and inherited @host rules - // 2. shim scoping: apply .scoped when available or pseudo-scoping when not - // (e.g. a selector 'div' becomes 'x-foo div') - shimShadowDOMStyling: function(styles, name) { - if (window.ShadowDOMPolyfill) { - stylizer.shimPolyfillDirectives(styles, name); - stylizer.applyShimming(styles, name); - } - }, - applyShimming: function(styles, name) { - var cssText = this.shimAtHost(styles, name); - cssText += this.shimScoping(styles, name); - this.addCssToDocument(cssText); - }, - cacheDefinition: function(element) { - var name = element.getAttribute('name'); - var content = element.templateContent(); - var styles = content && content.querySelectorAll('style'); - element.styles = styles ? slice(styles) : []; - stylizer.cache[name] = element; - }, - applyScopeToContent: function(root, name) { - if (root) { - forEach(root.querySelectorAll('*'), function(node) { - node.setAttribute(name, ''); - }); - forEach(root.querySelectorAll('template'), function(template) { - this.applyScopeToContent(templateContent(template), name); - }, this); - } - }, - stylesForElement: function(element) { - var styles = element.styles; - var content = element.templateContent(); - var shadow = content && content.querySelector('shadow'); - if (shadow || (content === null)) { - var extendee = this.findExtendee(element.getAttribute('name')); - if (extendee) { - var extendeeStyles = this.stylesForElement(extendee); - styles = concat(slice(extendeeStyles), slice(styles)); - } - } - return styles; - }, - findExtendee: function(name) { - var element = this.cache[name]; - return element && this.cache[element.getAttribute('extends')]; - }, - /* - * Process styles to convert native ShadowDOM rules that will trip - * up the css parser; we rely on decorating the stylesheet with comments. - * - * For example, we convert this rule: - * - * (comment start) @polyfill @host g-menu-item (comment end) - * shadow::-webkit-distributed(g-menu-item) { - * - * to this: - * - * scopeName g-menu-item { - * - **/ - shimPolyfillDirectives: function(styles, name) { - if (window.ShadowDOMPolyfill) { - if (styles) { - forEach(styles, function(s) { - s.textContent = this.convertPolyfillDirectives(s.textContent, name); - }, this); - } - } - }, - // form: @host { .foo { declarations } } - // becomes: scopeName.foo { declarations } - shimAtHost: function(styles, name) { - if (styles) { - return this.convertAtHostStyles(styles, name); - } - }, - /* Ensure styles are scoped. Pseudo-scoping takes a rule like: - * - * .foo {... } - * - * and converts this to - * - * scopeName .foo { ... } - */ - shimScoping: function(styles, name) { - if (styles) { - return this.convertScopedStyles(styles, name); - } - }, - convertPolyfillDirectives: function(cssText, name) { - var r = '', l = 0, matches, selector; - while (matches=this.cssPolyfillCommentRe.exec(cssText)) { - r += cssText.substring(l, matches.index); - // remove end comment delimiter (*/) - selector = matches[1].slice(0, -2).replace(this.hostRe, name); - r += this.scopeSelector(selector, name) + '{'; - l = this.cssPolyfillCommentRe.lastIndex; - } - r += cssText.substring(l, cssText.length); - return r; - }, - // consider styles that do not include component name in the selector to be - // unscoped and in need of promotion; - // for convenience, also consider keyframe rules this way. - findAtHostRules: function(cssRules, matcher) { - return Array.prototype.filter.call(cssRules, - this.isHostRule.bind(this, matcher)); - }, - isHostRule: function(matcher, cssRule) { - return (cssRule.selectorText && cssRule.selectorText.match(matcher)) || - (cssRule.cssRules && this.findAtHostRules(cssRule.cssRules, matcher).length) || - (cssRule.type == CSSRule.WEBKIT_KEYFRAMES_RULE); - }, - convertAtHostStyles: function(styles, name) { - var cssText = this.stylesToCssText(styles); - var r = '', l=0, matches; - while (matches=this.hostRuleRe.exec(cssText)) { - r += cssText.substring(l, matches.index); - r += this.scopeHostCss(matches[1], name); - l = this.hostRuleRe.lastIndex; - } - r += cssText.substring(l, cssText.length); - var selectorRe = new RegExp('^' + name + this.selectorReSuffix, 'm'); - var cssText = this.rulesToCss(this.findAtHostRules(this.cssToRules(r), - selectorRe)); - return cssText; - }, - scopeHostCss: function(cssText, name) { - var r = '', matches; - while (matches = this.selectorRe.exec(cssText)) { - r += this.scopeHostSelector(matches[1], name) +' ' + matches[2] + '\n\t'; - } - return r; - }, - // supports scopig by name and [is=name] syntax - scopeHostSelector: function(selector, name) { - var r = [], parts = selector.split(','), is = '[is=' + name + ']'; - parts.forEach(function(p) { - p = p.trim(); - // selector: *|:scope -> name - if (p.match(this.hostElementRe)) { - p = p.replace(this.hostElementRe, name + '$1$3, ' + is + '$1$3'); - // selector: .foo -> name.foo, [bar] -> name[bar] - } else if (p.match(this.hostFixableRe)) { - p = name + p + ', ' + is + p; - } - r.push(p); - }, this); - return r.join(', '); - }, - convertScopedStyles: function(styles, name) { - forEach(styles, function(s) { - if (s.parentNode) { - s.parentNode.removeChild(s); - } - }); - var cssText = this.stylesToCssText(styles).replace(this.hostRuleRe, ''); - cssText = this.convertPseudos(cssText); - var rules = this.cssToRules(cssText); - cssText = this.scopeRules(rules, name); - return cssText; - }, - convertPseudos: function(cssText) { - return cssText.replace(this.cssPseudoRe, ' [pseudo=$1]'); - }, - // change a selector like 'div' to 'name div' - scopeRules: function(cssRules, name) { - var cssText = ''; - forEach(cssRules, function(rule) { - if (rule.selectorText && (rule.style && rule.style.cssText)) { - cssText += this.scopeSelector(rule.selectorText, name, - Polymer.strictPolyfillStyling) + ' {\n\t'; - cssText += this.propertiesFromRule(rule) + '\n}\n\n'; - } else if (rule.media) { - cssText += '@media ' + rule.media.mediaText + ' {\n'; - cssText += this.scopeRules(rule.cssRules, name); - cssText += '\n}\n\n'; - } else if (rule.cssText) { - cssText += rule.cssText + '\n\n'; - } - }, this); - return cssText; - }, - propertiesFromRule: function(rule) { - var properties = rule.style.cssText; - // TODO(sorvell): Chrome cssom incorrectly removes quotes from the content - // property. (https://code.google.com/p/chromium/issues/detail?id=247231) - if (rule.style.content && !rule.style.content.match(/['"]+/)) { - properties = 'content: \'' + rule.style.content + '\';\n' + - rule.style.cssText.replace(/content:[^;]*;/g, ''); - } - return properties; - }, - selectorNeedsScoping: function(selector, name) { - var matchScope = '(' + name + '|\\[is=' + name + '\\])'; - var selectorRe = new RegExp('^' + matchScope + this.selectorReSuffix, 'm'); - return !selector.match(selectorRe); - }, - scopeSelector: function(selector, name, strict) { - var r = [], parts = selector.split(','); - parts.forEach(function(p) { - p = p.trim(); - if (this.selectorNeedsScoping(p, name)) { - p = strict ? this.applyStrictSelectorScope(p, name) : - this.applySimpleSelectorScope(p, name); - } - r.push(p); - }, this); - return r.join(', '); - }, - // scope via name and [is=name] - applySimpleSelectorScope: function(selector, name) { - return name + ' ' + selector + ', ' + '[is=' + name + '] ' + selector; - }, - // return a selector with [name] suffix on each simple selector - // e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name] - applyStrictSelectorScope: function(selector, name) { - var splits = [' ', '>', '+', '~'], - scoped = selector, - attrName = '[' + name + ']'; - splits.forEach(function(sep) { - var parts = scoped.split(sep); - scoped = parts.map(function(p) { - var t = p.trim(); - if (t && (splits.indexOf(t) < 0) && (t.indexOf(attrName) < 0)) { - p = t.replace(/([^:]*)(:*)(.*)/, '$1' + attrName + '$2$3') - } - return p; - }).join(sep); - }); - return scoped; - }, - stylesToCssText: function(styles, preserveComments) { - var cssText = ''; - forEach(styles, function(s) { - cssText += s.textContent + '\n\n'; - }); - // strip comments for easier processing - if (!preserveComments) { - cssText = this.stripCssComments(cssText); - } - return cssText; - }, - stripCssComments: function(cssText) { - return cssText.replace(this.cssCommentRe, ''); - }, - cssToRules: function(cssText) { - var style = document.createElement('style'); - style.textContent = cssText; - document.head.appendChild(style); - var rules = style.sheet.cssRules; - style.parentNode.removeChild(style); - return rules; - }, - rulesToCss: function(cssRules) { - for (var i=0, css=[]; i < cssRules.length; i++) { - css.push(cssRules[i].cssText); - } - return css.join('\n\n'); - }, - addCssToDocument: function(cssText) { - if (cssText) { - this.getSheet().appendChild(document.createTextNode(cssText)); - } - }, - // support for creating @host rules - getSheet: function() { - if (!this.sheet) { - this.sheet = document.createElement("style"); - this.sheet.setAttribute('polymer-polyfill', ''); - } - return this.sheet; - }, - addSheetToDocument: function() { - this.addCssToDocument('style { display: none !important; }\n'); - var head = document.querySelector('head'); - head.insertBefore(this.getSheet(), head.childNodes[0]); - } -}; - -// add polyfill stylesheet to document -if (window.ShadowDOMPolyfill) { - stylizer.addSheetToDocument(); -} - -// exports - -scope.shimStyling = stylizer.shimStyling; -scope.shimShadowDOMStyling = stylizer.shimShadowDOMStyling; -scope.shimPolyfillDirectives = stylizer.shimPolyfillDirectives.bind(stylizer); -scope.strictPolyfillStyling = false; - -})(Polymer); \ No newline at end of file From c1ac385cabe10d7e064f27c2c7f2407fe3fdbc45 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Mon, 29 Jul 2013 21:07:31 -0700 Subject: [PATCH 20/29] Use raw prototype traversal to ensure compatibility with platforms with simulated prototype chains (IE10) --- src/instance/styles.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/instance/styles.js b/src/instance/styles.js index df26d593d8..cd54407cc8 100644 --- a/src/instance/styles.js +++ b/src/instance/styles.js @@ -39,10 +39,10 @@ var scope = this.findStyleController(); if (scope && !this.scopeHasElementStyle(scope, STYLE_CONTROLLER_SCOPE)) { // allow inherited controller styles - var proto = Object.getPrototypeOf(this), cssText = ''; + var proto = getPrototypeOf(this), cssText = ''; while (proto && proto.element) { cssText += proto.element.cssTextForScope(STYLE_CONTROLLER_SCOPE); - proto = Object.getPrototypeOf(proto); + proto = getPrototypeOf(proto); } if (cssText) { var style = this.element.cssTextToScopeStyle(cssText, @@ -73,6 +73,12 @@ } } }; + + // NOTE: use raw prototype traversal so that we ensure correct traversal + // on platforms where the protoype chain is simulated via __proto__ (IE10) + function getPrototypeOf(prototype) { + return prototype.__proto__; + } // exports From fae6f96c345995618650871a88c2ebe725c7f5d0 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Mon, 29 Jul 2013 21:08:31 -0700 Subject: [PATCH 21/29] Ensure prototype traversal can be done during desugaring. --- src/declaration/polymer-element.js | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/declaration/polymer-element.js b/src/declaration/polymer-element.js index cdd4b75b9f..ce512d20ba 100644 --- a/src/declaration/polymer-element.js +++ b/src/declaration/polymer-element.js @@ -29,6 +29,20 @@ function generatePrototype(tag) { return Object.create(HTMLElement.getPrototypeForTag(tag)); } + + // On platforms that do not support __proto__ (IE10), the prototype chain + // of a custom element is simulated via installation of __proto__. + // Although custom elements manages this, we install it here so it's + // available during desuaring. + function ensurePrototypeTraversal(prototype) { + if (!Object.__proto__) { + var ancestor = Object.getPrototypeOf(prototype); + prototype.__proto__ = ancestor; + if (scope.isBase(ancestor)) { + ancestor.__proto__ = Object.getPrototypeOf(ancestor); + } + } + } // declarative implementation: @@ -66,17 +80,15 @@ // Potentially remove when spec bug is addressed. // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21407 this.addResolvePathApi(); + ensurePrototypeTraversal(this.prototype); + // declarative features + this.desugar(); // under ShadowDOMPolyfill, transforms to approximate missing CSS features if (window.ShadowDOMPolyfill) { Platform.ShadowCSS.shimStyling(this.templateContent(), name, extnds); } // register our custom element this.register(name); - // declarative features - // NOTE: make sure to desugar after calling register. Registration - // ensures the __proto__ chain exists on platforms that don't support it - // natively (IE10), and desugar uses the __proto__ chain. - this.desugar(); // reference constructor in a global named by 'constructor' attribute this.publishConstructor(); }, From 62e0233e08f62b140eb050c841d8e5a0876f8af1 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Tue, 30 Jul 2013 19:25:46 -0700 Subject: [PATCH 22/29] Polymer supports entered/leftDocument, note that inserted/removed are supported for bc. --- src/instance/base.js | 34 ++++++++++++++++++++++++++++++++++ src/instance/mdv.js | 14 -------------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/instance/base.js b/src/instance/base.js index 7fbbf38ec7..09289253f7 100644 --- a/src/instance/base.js +++ b/src/instance/base.js @@ -42,6 +42,40 @@ // user initialization this.ready(); }, + insertedCallback: function() { + this._enteredDocumentCallback(); + }, + enteredDocumentCallback: function() { + this._enteredDocumentCallback(); + }, + _enteredDocumentCallback: function() { + this.cancelUnbindAll(true); + // TODO(sorvell): bc + if (this.inserted) { + this.inserted(); + } + // invoke user action + if (this.enteredDocument) { + this.enteredDocument(); + } + }, + removedCallback: function() { + this._leftDocumentCallback(); + }, + leftDocumentCallback: function() { + this._leftDocumentCallback(); + }, + _leftDocumentCallback: function() { + this.asyncUnbindAll(); + // TODO(sorvell): bc + if (this.removed) { + this.removed(); + } + // invoke user action + if (this.leftDocument) { + this.leftDocument(); + } + }, // recursive ancestral initialization, oldest first parseElements: function(p) { if (p && p.element) { diff --git a/src/instance/mdv.js b/src/instance/mdv.js index 62b01f502f..f206e32f46 100644 --- a/src/instance/mdv.js +++ b/src/instance/mdv.js @@ -66,20 +66,6 @@ } }); } - }, - insertedCallback: function() { - this.cancelUnbindAll(true); - // invoke user 'inserted' - if (this.inserted) { - this.inserted(); - } - }, - removedCallback: function() { - this.asyncUnbindAll(); - // invoke user 'removed' - if (this.removed) { - this.removed(); - } } }; From c65e5fc7e099c8921dd218fbe5da67cad31e65ee Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Wed, 31 Jul 2013 09:39:18 -0700 Subject: [PATCH 23/29] ensure elements used for testing are uniquely named (elements cannot be re-declared). --- test/js/events.js | 6 +++--- test/js/register.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/js/events.js b/test/js/events.js index ceb3a4ebbd..b92bfaf696 100644 --- a/test/js/events.js +++ b/test/js/events.js @@ -32,14 +32,14 @@ suite('events', function() { } test('host event', function(done) { - createTestElement('x-foo'); + createTestElement('x-events-foo'); // Ensure IE goes... CustomElements.takeRecords(); setTimeout(function() { - var foo = document.createElement('x-foo'); + var foo = document.createElement('x-events-foo'); work.appendChild(foo); foo.click(); - assert.equal(results.textContent, 'x-foo'); + assert.equal(results.textContent, 'x-events-foo'); done(); }, 0); }); diff --git a/test/js/register.js b/test/js/register.js index 93a1e39d81..4ff02de121 100644 --- a/test/js/register.js +++ b/test/js/register.js @@ -19,7 +19,7 @@ suite('register', function() { }); test('register', function(done) { - Polymer('x-foo', { + Polymer('x-register-foo', { ready: function() { this.message = 'foo'; }, @@ -27,11 +27,11 @@ suite('register', function() { this.message = 'hello'; } }); - work.innerHTML = ''; + work.innerHTML = ''; // Ensure IE goes... CustomElements.takeRecords(); setTimeout(function() { - var foo = document.createElement('x-foo'); + var foo = document.createElement('x-register-foo'); // test ready assert.equal(foo.message, 'foo'); // test sayHello From b8d7654561ef2bd62668c12e45b0dd52c749ab24 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Wed, 31 Jul 2013 11:15:53 -0700 Subject: [PATCH 24/29] remove use of noscript. --- test/html/element-script.html | 16 +++++++++++++--- test/html/prop-attr-reflection.html | 6 +++++- test/html/publish-attributes.html | 10 ++++++++-- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/test/html/element-script.html b/test/html/element-script.html index 354e1325ac..dce5dd3998 100644 --- a/test/html/element-script.html +++ b/test/html/element-script.html @@ -34,17 +34,23 @@ - + + - + + @@ -70,7 +76,11 @@ } }); - + + + diff --git a/test/html/prop-attr-reflection.html b/test/html/prop-attr-reflection.html index 1404f2cfac..b404c6ad84 100644 --- a/test/html/prop-attr-reflection.html +++ b/test/html/prop-attr-reflection.html @@ -9,7 +9,11 @@ - + + + diff --git a/test/html/publish-attributes.html b/test/html/publish-attributes.html index 1c98289c93..c38f055dbd 100644 --- a/test/html/publish-attributes.html +++ b/test/html/publish-attributes.html @@ -8,10 +8,16 @@ - + + - + + From 9d2beb8db8e708d0fd15098e177eeb5baa659aee Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Wed, 31 Jul 2013 11:27:46 -0700 Subject: [PATCH 25/29] remove noscript feature for now --- src/declaration/polymer-element.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declaration/polymer-element.js b/src/declaration/polymer-element.js index ce512d20ba..5c827c082e 100644 --- a/src/declaration/polymer-element.js +++ b/src/declaration/polymer-element.js @@ -59,7 +59,7 @@ _createdCallback: function() { // fetch our element name var name = this.getAttribute('name'); - if (registry[name] || this.hasAttribute('noscript')) { + if (registry[name]) { this.define(); } else { deferred[name] = this; From 92dbcaf317d0023e5f59dd5c39e8223fa182a065 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Wed, 31 Jul 2013 14:32:19 -0700 Subject: [PATCH 26/29] correct test so that it includes proper scripts --- test/html/element-script.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/html/element-script.html b/test/html/element-script.html index dce5dd3998..e9c0029b10 100644 --- a/test/html/element-script.html +++ b/test/html/element-script.html @@ -24,13 +24,16 @@
-
+ From 44b30e117f0fabe4af7499fe42e3a51f89a4a57f Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Wed, 31 Jul 2013 18:47:50 -0700 Subject: [PATCH 27/29] update sheet-main-doc test. --- test/html/styling/sheet-main-doc.html | 13 +++---------- test/html/styling/x-sheet-main-doc.html | 8 ++++++++ 2 files changed, 11 insertions(+), 10 deletions(-) create mode 100644 test/html/styling/x-sheet-main-doc.html diff --git a/test/html/styling/sheet-main-doc.html b/test/html/styling/sheet-main-doc.html index 1ae0d4053a..5edee1d26d 100644 --- a/test/html/styling/sheet-main-doc.html +++ b/test/html/styling/sheet-main-doc.html @@ -11,21 +11,14 @@ + - +
red
- - - - +
From 0f96e2734333e252dc7fba9168a4f2b32139c827 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Wed, 31 Jul 2013 18:48:55 -0700 Subject: [PATCH 28/29] revert element-script test: currently passes under polyfill and not native custom elements --- test/html/element-script.html | 9 --------- 1 file changed, 9 deletions(-) diff --git a/test/html/element-script.html b/test/html/element-script.html index e9c0029b10..48cb7e24d9 100644 --- a/test/html/element-script.html +++ b/test/html/element-script.html @@ -31,9 +31,6 @@ -
@@ -41,9 +38,6 @@ -
@@ -80,9 +74,6 @@ }); - From 6e0338c7f6873792520b5f4b5b6fe6898146aaa7 Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Thu, 1 Aug 2013 12:29:06 -0700 Subject: [PATCH 29/29] do not consider null valued prototype an indicator that a property should be deserialized as an object. --- src/lib/deserialize.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/deserialize.js b/src/lib/deserialize.js index 84f4f398f7..e1f434920b 100644 --- a/src/lib/deserialize.js +++ b/src/lib/deserialize.js @@ -24,6 +24,9 @@ return (String(floatVal) === value) ? floatVal : value; }, 'object': function(value, defaultValue) { + if (defaultValue === null) { + return value; + } try { // If the string is an object, we can parse is with the JSON library. // include convenience replace for single-quotes. If the author omits