Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(228)

Unified Diff: dart/pkg/shadow_dom/lib/shadow_dom.debug.js

Issue 59073003: Version 0.8.10.4 (Closed) Base URL: http://dart.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « dart/pkg/polymer/test/build/script_compactor_test.dart ('k') | dart/pkg/shadow_dom/lib/shadow_dom.min.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dart/pkg/shadow_dom/lib/shadow_dom.debug.js
===================================================================
--- dart/pkg/shadow_dom/lib/shadow_dom.debug.js (revision 29808)
+++ dart/pkg/shadow_dom/lib/shadow_dom.debug.js (working copy)
@@ -1884,7 +1884,7 @@
// 1.
if (isShadowRoot(node))
- return getInsertionParent(node) || scope.getHostForShadowRoot(node);
+ return getInsertionParent(node) || node.host;
// 2.
var eventParents = scope.eventParentsTable.get(node);
@@ -1980,7 +1980,7 @@
ancestor = calculateParents(ancestor, context, ancestors); // 3.4.7.
}
if (isShadowRoot(target)) // 3.5.
- target = scope.getHostForShadowRoot(target);
+ target = target.host;
else
target = target.parentNode; // 3.6.
}
@@ -2009,10 +2009,8 @@
function enclosedBy(a, b) {
if (a === b)
return true;
- if (a instanceof wrappers.ShadowRoot) {
- var host = scope.getHostForShadowRoot(a);
- return enclosedBy(rootOfNode(host), b);
- }
+ if (a instanceof wrappers.ShadowRoot)
+ return enclosedBy(rootOfNode(a.host), b);
return false;
}
@@ -2434,7 +2432,7 @@
function getTargetToListenAt(wrapper) {
if (wrapper instanceof wrappers.ShadowRoot)
- wrapper = scope.getHostForShadowRoot(wrapper);
+ wrapper = wrapper.host;
return unwrap(wrapper);
}
@@ -2671,13 +2669,15 @@
}
var nodes = [];
- var firstChild;
- while (firstChild = node.firstChild) {
- node.removeChild(firstChild);
- nodes.push(firstChild);
- firstChild.parentNode_ = parentNode;
+ for (var child = node.firstChild; child; child = child.nextSibling) {
+ nodes.push(child);
}
+ for (var i = nodes.length - 1; i >= 0; i--) {
+ node.removeChild(nodes[i]);
+ nodes[i].parentNode_ = parentNode;
+ }
+
for (var i = 0; i < nodes.length; i++) {
nodes[i].previousSibling_ = nodes[i - 1] || previousNode;
nodes[i].nextSibling_ = nodes[i + 1] || nextNode;
@@ -2825,13 +2825,29 @@
this.previousSibling_ = undefined;
};
+ var OriginalDocumentFragment = window.DocumentFragment;
var originalAppendChild = OriginalNode.prototype.appendChild;
+ var originalCompareDocumentPosition =
+ OriginalNode.prototype.compareDocumentPosition;
var originalInsertBefore = OriginalNode.prototype.insertBefore;
+ var originalRemoveChild = OriginalNode.prototype.removeChild;
var originalReplaceChild = OriginalNode.prototype.replaceChild;
- var originalRemoveChild = OriginalNode.prototype.removeChild;
- var originalCompareDocumentPosition =
- OriginalNode.prototype.compareDocumentPosition;
+ var isIe = /Trident/.test(navigator.userAgent);
+
+ var removeChildOriginalHelper = isIe ?
+ function(parent, child) {
+ try {
+ originalRemoveChild.call(parent, child);
+ } catch (ex) {
+ if (!(parent instanceof OriginalDocumentFragment))
+ throw ex;
+ }
+ } :
+ function(parent, child) {
+ originalRemoveChild.call(parent, child);
+ };
+
Node.prototype = Object.create(EventTarget.prototype);
mixin(Node.prototype, {
appendChild: function(childWrapper) {
@@ -2906,8 +2922,20 @@
removeChild: function(childWrapper) {
assertIsNodeWrapper(childWrapper);
if (childWrapper.parentNode !== this) {
- // TODO(arv): DOMException
- throw new Error('NotFoundError');
+ // IE has invalid DOM trees at times.
+ var found = false;
+ var childNodes = this.childNodes;
+ for (var ieChild = this.firstChild; ieChild;
+ ieChild = ieChild.nextSibling) {
+ if (ieChild === childWrapper) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ // TODO(arv): DOMException
+ throw new Error('NotFoundError');
+ }
}
var childNode = unwrap(childWrapper);
@@ -2923,7 +2951,7 @@
var parentNode = childNode.parentNode;
if (parentNode)
- originalRemoveChild.call(parentNode, childNode);
+ removeChildOriginalHelper(parentNode, childNode);
if (thisFirstChild === childWrapper)
this.firstChild_ = childWrapperNextSibling;
@@ -2939,7 +2967,7 @@
childWrapper.previousSibling_ = childWrapper.nextSibling_ =
childWrapper.parentNode_ = undefined;
} else {
- originalRemoveChild.call(this.impl, childNode);
+ removeChildOriginalHelper(this.impl, childNode);
}
return childWrapper;
@@ -3726,12 +3754,13 @@
}
var node = unwrap(document.createElement('img'));
+ HTMLElement.call(this, node);
+ rewrap(node, this);
+
if (width !== undefined)
node.width = width;
if (height !== undefined)
node.height = height;
- HTMLElement.call(this, node);
- rewrap(node, this);
}
Image.prototype = HTMLImageElement.prototype;
@@ -3858,6 +3887,136 @@
(function(scope) {
'use strict';
+ var HTMLElement = scope.wrappers.HTMLElement;
+ var registerWrapper = scope.registerWrapper;
+
+ var OriginalHTMLMediaElement = window.HTMLMediaElement;
+
+ function HTMLMediaElement(node) {
+ HTMLElement.call(this, node);
+ }
+ HTMLMediaElement.prototype = Object.create(HTMLElement.prototype);
+
+ registerWrapper(OriginalHTMLMediaElement, HTMLMediaElement,
+ document.createElement('audio'));
+
+ scope.wrappers.HTMLMediaElement = HTMLMediaElement;
+})(this.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+ 'use strict';
+
+ var HTMLMediaElement = scope.wrappers.HTMLMediaElement;
+ var registerWrapper = scope.registerWrapper;
+ var unwrap = scope.unwrap;
+ var rewrap = scope.rewrap;
+
+ var OriginalHTMLAudioElement = window.HTMLAudioElement;
+
+ function HTMLAudioElement(node) {
+ HTMLMediaElement.call(this, node);
+ }
+ HTMLAudioElement.prototype = Object.create(HTMLMediaElement.prototype);
+
+ registerWrapper(OriginalHTMLAudioElement, HTMLAudioElement,
+ document.createElement('audio'));
+
+ function Audio(src) {
+ if (!(this instanceof Audio)) {
+ throw new TypeError(
+ 'DOM object constructor cannot be called as a function.');
+ }
+
+ var node = unwrap(document.createElement('audio'));
+ HTMLMediaElement.call(this, node);
+ rewrap(node, this);
+
+ node.setAttribute('preload', 'auto');
+ if (src !== undefined)
+ node.setAttribute('src', src);
+ }
+
+ Audio.prototype = HTMLAudioElement.prototype;
+
+ scope.wrappers.HTMLAudioElement = HTMLAudioElement;
+ scope.wrappers.Audio = Audio;
+})(this.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+ 'use strict';
+
+ var HTMLElement = scope.wrappers.HTMLElement;
+ var mixin = scope.mixin;
+ var registerWrapper = scope.registerWrapper;
+ var rewrap = scope.rewrap;
+ var unwrap = scope.unwrap;
+ var wrap = scope.wrap;
+
+ var OriginalHTMLOptionElement = window.HTMLOptionElement;
+
+ function trimText(s) {
+ return s.replace(/\s+/g, ' ').trim();
+ }
+
+ function HTMLOptionElement(node) {
+ HTMLElement.call(this, node);
+ }
+ HTMLOptionElement.prototype = Object.create(HTMLElement.prototype);
+ mixin(HTMLOptionElement.prototype, {
+ get text() {
+ return trimText(this.textContent);
+ },
+ set text(value) {
+ this.textContent = trimText(String(value));
+ },
+ get form() {
+ return wrap(unwrap(this).form);
+ }
+ });
+
+ registerWrapper(OriginalHTMLOptionElement, HTMLOptionElement,
+ document.createElement('option'));
+
+ function Option(text, value, defaultSelected, selected) {
+ if (!(this instanceof Option)) {
+ throw new TypeError(
+ 'DOM object constructor cannot be called as a function.');
+ }
+
+ var node = unwrap(document.createElement('option'));
+ HTMLElement.call(this, node);
+ rewrap(node, this);
+
+ if (text !== undefined)
+ node.text = text;
+ if (value !== undefined)
+ node.setAttribute('value', value);
+ if (defaultSelected === true)
+ node.setAttribute('selected', '');
+ node.selected = selected === true;
+ }
+
+ Option.prototype = HTMLOptionElement.prototype;
+
+ scope.wrappers.HTMLOptionElement = HTMLOptionElement;
+ scope.wrappers.Option = Option;
+})(this.ShadowDOMPolyfill);
+
+// Copyright 2013 The Polymer Authors. All rights reserved.
+// Use of this source code is goverened by a BSD-style
+// license that can be found in the LICENSE file.
+
+(function(scope) {
+ 'use strict';
+
var HTMLContentElement = scope.wrappers.HTMLContentElement;
var HTMLElement = scope.wrappers.HTMLElement;
var HTMLShadowElement = scope.wrappers.HTMLShadowElement;
@@ -4037,6 +4196,10 @@
return nextOlderShadowTreeTable.get(this) || null;
},
+ get host() {
+ return shadowHostTable.get(this) || null;
+ },
+
invalidateShadowRenderer: function() {
return shadowHostTable.get(this).invalidateShadowRenderer();
},
@@ -4051,9 +4214,6 @@
});
scope.wrappers.ShadowRoot = ShadowRoot;
- scope.getHostForShadowRoot = function(node) {
- return shadowHostTable.get(node);
- };
})(this.ShadowDOMPolyfill);
// Copyright 2013 The Polymer Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -4068,7 +4228,6 @@
var Node = scope.wrappers.Node;
var ShadowRoot = scope.wrappers.ShadowRoot;
var assert = scope.assert;
- var getHostForShadowRoot = scope.getHostForShadowRoot;
var mixin = scope.mixin;
var muteMutationEvents = scope.muteMutationEvents;
var oneOf = scope.oneOf;
@@ -4310,7 +4469,7 @@
}
function getRendererForShadowRoot(shadowRoot) {
- return getRendererForHost(getHostForShadowRoot(shadowRoot));
+ return getRendererForHost(shadowRoot.host);
}
var spliceDiff = new ArraySplice();
@@ -4739,7 +4898,7 @@
'HTMLLabelElement',
'HTMLLegendElement',
'HTMLObjectElement',
- 'HTMLOptionElement',
+ // HTMLOptionElement is handled in HTMLOptionElement.js
'HTMLOutputElement',
'HTMLSelectElement',
'HTMLTextAreaElement',
@@ -4924,13 +5083,19 @@
};
});
- var nativeConstructor = originalRegister.call(unwrap(this), tagName,
- object.extends ? {prototype: newPrototype, extends: object.extends} :
- {prototype: newPrototype});
+ var p = {prototype: newPrototype};
+ if (object.extends)
+ p.extends = object.extends;
+ var nativeConstructor = originalRegister.call(unwrap(this), tagName, p);
function GeneratedWrapper(node) {
- if (!node)
- return document.createElement(tagName);
+ if (!node) {
+ if (object.extends) {
+ return document.createElement(object.extends, tagName);
+ } else {
+ return document.createElement(tagName);
+ }
+ }
this.impl = node;
}
GeneratedWrapper.prototype = prototype;
@@ -5304,7 +5469,6 @@
'a': 'HTMLAnchorElement',
'applet': 'HTMLAppletElement',
'area': 'HTMLAreaElement',
- 'audio': 'HTMLAudioElement',
'br': 'HTMLBRElement',
'base': 'HTMLBaseElement',
'body': 'HTMLBodyElement',
@@ -5333,7 +5497,6 @@
'link': 'HTMLLinkElement',
'map': 'HTMLMapElement',
'marquee': 'HTMLMarqueeElement',
- // 'media', Covered by audio and video
'menu': 'HTMLMenuElement',
'menuitem': 'HTMLMenuItemElement',
'meta': 'HTMLMetaElement',
@@ -5477,10 +5640,10 @@
/*
This is a limited shim for ShadowDOM css styling.
https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#styles
-
- The intention here is to support only the styling features which can be
- relatively simply implemented. The goal is to allow users to avoid the
- most obvious pitfalls and do so without compromising performance significantly.
+
+ The intention here is to support only the styling features which can be
+ relatively simply implemented. The goal is to allow users to avoid the
+ most obvious pitfalls and do so without compromising performance significantly.
For ShadowDOM styling that's not covered here, a set of best practices
can be provided that should allow users to accomplish more complex styling.
@@ -5489,57 +5652,57 @@
Shimmed features:
- * @host: ShadowDOM allows styling of the shadowRoot's host element using the
- @host rule. To shim this feature, the @host styles are reformatted and
+ * @host: ShadowDOM allows styling of the shadowRoot's host element using the
+ @host rule. To shim this feature, the @host styles are reformatted and
prefixed with a given scope name and promoted to a document level stylesheet.
For example, given a scope name of .foo, a rule like this:
-
+
@host {
* {
background: red;
}
}
-
+
becomes:
-
+
.foo {
background: red;
}
-
- * encapsultion: Styles defined within ShadowDOM, apply only to
+
+ * encapsultion: Styles defined within ShadowDOM, apply only to
dom inside the ShadowDOM. Polymer uses one of two techniques to imlement
this feature.
-
- By default, rules are prefixed with the host element tag name
+
+ By default, rules are prefixed with the host element tag name
as a descendant selector. This ensures styling does not leak out of the 'top'
of the element's ShadowDOM. For example,
div {
font-weight: bold;
}
-
+
becomes:
x-foo div {
font-weight: bold;
}
-
+
becomes:
- Alternatively, if Platform.ShadowCSS.strictStyling is set to true then
+ Alternatively, if Platform.ShadowCSS.strictStyling is set to true then
selectors are scoped by adding an attribute selector suffix to each
- simple selector that contains the host element tag name. Each element
- in the element's ShadowDOM template is also given the scope attribute.
+ simple selector that contains the host element tag name. Each element
+ in the element's ShadowDOM template is also given the scope attribute.
Thus, these rules match only elements that have the scope attribute.
For example, given a scope name of x-foo, a rule like this:
-
+
div {
font-weight: bold;
}
-
+
becomes:
-
+
div[x-foo] {
font-weight: bold;
}
@@ -5571,39 +5734,39 @@
becomes:
- x-foo [part=special] { ... }
-
+ x-foo [part=special] { ... }
+
Unaddressed ShadowDOM styling features:
-
+
* upper/lower bound encapsulation: Styles which are defined outside a
shadowRoot should not cross the ShadowDOM boundary and should not apply
inside a shadowRoot.
- This styling behavior is not emulated. Some possible ways to do this that
+ This styling behavior is not emulated. Some possible ways to do this that
were rejected due to complexity and/or performance concerns include: (1) reset
every possible property for every possible selector for a given scope name;
(2) re-implement css in javascript.
-
+
As an alternative, users should make sure to use selectors
specific to the scope in which they are working.
-
+
* ::distributed: This behavior is not emulated. It's often not necessary
to style the contents of a specific insertion point and instead, descendants
- of the host element can be styled selectively. Users can also create an
+ of the host element can be styled selectively. Users can also create an
extra node around an insertion point and style that node's contents
via descendent selectors. For example, with a shadowRoot like this:
-
+
<style>
content::-webkit-distributed(div) {
background: red;
}
</style>
<content></content>
-
+
could become:
-
+
<style>
- / *@polyfill .content-container div * /
+ / *@polyfill .content-container div * /
content::-webkit-distributed(div) {
background: red;
}
@@ -5611,9 +5774,9 @@
<div class="content-container">
<content></content>
</div>
-
+
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
+ 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) {
@@ -5649,7 +5812,7 @@
root.shimmedStyle = def.shimmedStyle;
}
// remove existing style elements
- for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]);
+ for (var i=0, l=def.rootStyles.length, s; (i<l) && (s=def.rootStyles[i]);
i++) {
s.parentNode.removeChild(s);
}
@@ -5693,14 +5856,14 @@
/*
* 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 menu-item (comment end)
* shadow::-webkit-distributed(menu-item) {
- *
+ *
* to this:
- *
+ *
* scopeName menu-item {
*
**/
@@ -5719,14 +5882,14 @@
},
/*
* Process styles to add rules which will only apply under the polyfill
- *
+ *
* For example, we convert this rule:
- *
- * (comment start) @polyfill-rule :host menu-item {
+ *
+ * (comment start) @polyfill-rule :host menu-item {
* ... } (comment end)
- *
+ *
* to this:
- *
+ *
* scopeName menu-item {...}
*
**/
@@ -5745,15 +5908,15 @@
},
/*
* Process styles to add rules which will only apply under the polyfill
- * and do not process via CSSOM. (CSSOM is destructive to rules on rare
+ * and do not process via CSSOM. (CSSOM is destructive to rules on rare
* occasions, e.g. -webkit-calc on Safari.)
* For example, we convert this rule:
- *
- * (comment start) @polyfill-unscoped-rule menu-item {
+ *
+ * (comment start) @polyfill-unscoped-rule menu-item {
* ... } (comment end)
- *
+ *
* to this:
- *
+ *
* menu-item {...}
*
**/
@@ -5792,7 +5955,7 @@
return self.scopeHostCss(p1, name, typeExtension);
});
cssText = rulesToCss(this.findAtHostRules(cssToRules(cssText),
- new RegExp('^' + name + selectorReSuffix, 'm')));
+ this.makeScopeMatcher(name, typeExtension)));
return cssText;
},
scopeHostCss: function(cssText, name, typeExtension) {
@@ -5819,10 +5982,10 @@
return r.join(', ');
},
// consider styles that do not include component name in the selector to be
- // unscoped and in need of promotion;
+ // unscoped and in need of promotion;
// for convenience, also consider keyframe rules this way.
findAtHostRules: function(cssRules, matcher) {
- return Array.prototype.filter.call(cssRules,
+ return Array.prototype.filter.call(cssRules,
this.isHostRule.bind(this, matcher));
},
isHostRule: function(matcher, cssRule) {
@@ -5831,11 +5994,11 @@
(cssRule.type == CSSRule.WEBKIT_KEYFRAMES_RULE);
},
/* Ensure styles are scoped. Pseudo-scoping takes a rule like:
- *
- * .foo {... }
- *
+ *
+ * .foo {... }
+ *
* and converts this to
- *
+ *
* scopeName .foo { ... }
*/
shimScoping: function(styles, name, typeExtension) {
@@ -5866,15 +6029,28 @@
* to
*
* scopeName.foo > .bar, .foo scopeName > .bar { }
- * TODO(sorvell): file bug since native impl does not do the former yet.
- * http://jsbin.com/OganOCI/2/edit
+ *
+ * and
+ *
+ * :host(.foo:host) .bar { ... }
+ *
+ * to
+ *
+ * scopeName.foo .bar { ... }
*/
convertColonHost: function(cssText) {
// p1 = :host, p2 = contents of (), p3 rest of rule
return cssText.replace(cssColonHostRe, function(m, p1, p2, p3) {
- return p2 ? polyfillHostNoCombinator + p2 + p3 + ', '
- + p2 + ' ' + p1 + p3 :
- p1 + p3;
+ p1 = polyfillHostNoCombinator;
+ if (p2) {
+ if (p2.match(polyfillHost)) {
+ return p1 + p2.replace(polyfillHost, '') + p3;
+ } else {
+ return p1 + p2 + p3 + ', ' + p2 + ' ' + p1 + p3;
+ }
+ } else {
+ return p1 + p3;
+ }
});
},
/*
@@ -5888,7 +6064,7 @@
var cssText = '';
Array.prototype.forEach.call(cssRules, function(rule) {
if (rule.selectorText && (rule.style && rule.style.cssText)) {
- cssText += this.scopeSelector(rule.selectorText, name, typeExtension,
+ cssText += this.scopeSelector(rule.selectorText, name, typeExtension,
this.strictStyling) + ' {\n\t';
cssText += this.propertiesFromRule(rule) + '\n}\n\n';
} else if (rule.media) {
@@ -5914,10 +6090,13 @@
return r.join(', ');
},
selectorNeedsScoping: function(selector, name, typeExtension) {
- var matchScope = typeExtension ? name : '\\[is=' + name + '\\]';
- var re = new RegExp('^(' + matchScope + ')' + selectorReSuffix, 'm');
+ var re = this.makeScopeMatcher(name, typeExtension);
return !selector.match(re);
},
+ makeScopeMatcher: function(name, typeExtension) {
+ var matchScope = typeExtension ? '\\[is=[\'"]?' + name + '[\'"]?\\]' : name;
+ return new RegExp('^(' + matchScope + ')' + selectorReSuffix, 'm');
+ },
// scope via name and [is=name]
applySimpleSelectorScope: function(selector, name, typeExtension) {
var scoper = typeExtension ? '[is=' + name + ']' : name;
@@ -5956,7 +6135,7 @@
// 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' +
+ properties = 'content: \'' + rule.style.content + '\';\n' +
rule.style.cssText.replace(/content:[^;]*;/g, '');
}
return properties;
@@ -6042,5 +6221,4 @@
scope.ShadowCSS = ShadowCSS;
})(window.Platform);
-
}
« no previous file with comments | « dart/pkg/polymer/test/build/script_compactor_test.dart ('k') | dart/pkg/shadow_dom/lib/shadow_dom.min.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698