Skip to content
This repository was archived by the owner on Mar 13, 2018. It is now read-only.

Commit 849adf7

Browse files
committed
Merge pull request #41 from Polymer/master
6/17 master -> stable
2 parents bb7369f + d6187fa commit 849adf7

15 files changed

Lines changed: 177 additions & 177 deletions

.gitmodules

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
[submodule "buildbot"]
2-
path = buildbot
3-
url = https://github.com/Polymer/buildbot.git
41
[submodule "MutationObservers"]
52
path = MutationObservers
63
url = https://github.com/Polymer/MutationObservers.git

README.md

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Custom elements are still elements. We can create, use, manipulate, and compose
1313
### Basic usage
1414

1515
As with any element, custom elements can be created in JavaScript or declared.
16-
**Their name must always contain a dash (-).**
16+
**Custom element names must always contain a dash (-).**
1717

1818
#### Element registration
1919

@@ -89,13 +89,13 @@ declare the type using the `extends` option when calling `document.register()`:
8989

9090
Example extending `button`:
9191

92-
var XFooPrototype = Object.create(HTMLButtonElement.prototype);
93-
XFooPrototype.readyCallback = function() {
94-
this.textContent = "I'm an x-foo!";
92+
var XFooButtonPrototype = Object.create(HTMLButtonElement.prototype);
93+
XFooButtonPrototype.readyCallback = function() {
94+
this.textContent = "I'm an x-foo button!";
9595
};
9696

97-
var XFoo = document.register('x-foo', {
98-
prototype: XFooPrototype,
97+
var XFooButton = document.register('x-foo-button', {
98+
prototype: XFooButtonPrototype,
9999
extends: 'button'
100100
});
101101

@@ -106,13 +106,22 @@ standard DOM elements:
106106

107107
<x-foo></x-foo>
108108

109-
In the declarative and `document.register()` examples above, `XFoo` was defined as the new element's constructor. Browser limitations require that we supply the constructor while you supply the prototype. Use the `readyCallback` to do initialization work that might otherwise be in the constructor.
109+
If you've used `extends` to create a custom element that derives from an existing DOM element
110+
(e.g. something other than `HTMLElement`), use the `is` syntax:
111+
112+
<button is="x-foo-button"></button>
113+
114+
In the declarative and `document.register()` example above, `XFoo` was defined as the new element's constructor.
115+
This can also be used to create an instance:
110116

111117
var xFoo = new XFoo();
112118
document.body.appendChild(xFoo);
113119

114-
var xFoo2 = document.createElement('x-foo');
115-
xFoo2.foo(); // "foo() called"
120+
var xFooButton = document.createElement('button', 'x-foo-button');
121+
xFooButton.foo(); // "foo() called"
122+
123+
Browser limitations require that we supply the constructor while you supply the `prototype`.
124+
Use the `readyCallback` to do initialization work that might otherwise be in a constructor.
116125

117126
## Polyfill details
118127

buildbot

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/CustomElements.js

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,16 @@ function register(inName, inOptions) {
105105
// some platforms require modifications to the user-supplied prototype
106106
// chain
107107
resolvePrototypeChain(definition);
108-
// overrides to implement callbacks
109-
// TODO(sjmiles): should support access via .attributes NamedNodeMap
110-
definition.prototype.setAttribute = setAttribute;
111-
definition.prototype.removeAttribute = removeAttribute;
108+
// overrides to implement attributeChanged callback
109+
overrideAttributeApi(definition.prototype);
112110
// 7.1.5: Register the DEFINITION with DOCUMENT
113111
registerDefinition(inName, definition);
114112
// 7.1.7. Run custom element constructor generation algorithm with PROTOTYPE
115113
// 7.1.8. Return the output of the previous step.
116114
definition.ctor = generateConstructor(definition);
117115
definition.ctor.prototype = definition.prototype;
116+
// force our .constructor to be our actual constructor
117+
definition.prototype.constructor = definition.ctor;
118118
// if initial parsing is complete
119119
if (scope.ready) {
120120
// upgrade any pre-existing nodes of this type
@@ -152,13 +152,12 @@ function resolvePrototypeChain(inDefinition) {
152152
// if we don't support __proto__ we need to locate the native level
153153
// prototype for precise mixing in
154154
if (!Object.__proto__) {
155+
// default prototype
156+
var native = HTMLElement.prototype;
157+
// work out prototype when using type-extension
155158
if (inDefinition.is) {
156-
// for non-trivial extensions, work out both prototypes
157159
var inst = document.createElement(inDefinition.tag);
158-
var native = Object.getPrototypeOf(inst);
159-
} else {
160-
// otherwise, use the default
161-
native = HTMLElement.prototype;
160+
native = Object.getPrototypeOf(inst);
162161
}
163162
}
164163
// cache this in case of mixin
@@ -241,15 +240,18 @@ function ready(inElement) {
241240

242241
// attribute watching
243242

244-
var originalSetAttribute = HTMLElement.prototype.setAttribute;
245-
var originalRemoveAttribute = HTMLElement.prototype.removeAttribute;
246-
247-
function setAttribute(name, value) {
248-
changeAttribute.call(this, name, value, originalSetAttribute);
249-
}
250-
251-
function removeAttribute(name, value) {
252-
changeAttribute.call(this, name, value, originalRemoveAttribute);
243+
function overrideAttributeApi(prototype) {
244+
// overrides to implement callbacks
245+
// TODO(sjmiles): should support access via .attributes NamedNodeMap
246+
// TODO(sjmiles): preserves user defined overrides, if any
247+
var setAttribute = prototype.setAttribute;
248+
prototype.setAttribute = function(name, value) {
249+
changeAttribute.call(this, name, value, setAttribute);
250+
}
251+
var removeAttribute = prototype.removeAttribute;
252+
prototype.removeAttribute = function(name, value) {
253+
changeAttribute.call(this, name, value, removeAttribute);
254+
}
253255
}
254256

255257
function changeAttribute(name, value, operation) {

src/HTMLElementElement.js

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ function executeComponentScript(inScript, inContext, inName) {
9797
+ "', function(){"
9898
+ inScript
9999
+ "});"
100-
+ "\n//@ sourceURL=" + url + "\n"
100+
+ "\n//# sourceURL=" + url + "\n"
101101
;
102102
// inject script
103103
eval(code);
@@ -112,40 +112,23 @@ window.__componentScript = function(inName, inFunc) {
112112

113113
// utility
114114

115-
// copy all properties from inProps (et al) to inObj
116-
function mixin(inObj/*, inProps, inMoreProps, ...*/) {
117-
var obj = inObj || {};
118-
for (var i = 1; i < arguments.length; i++) {
119-
var p = arguments[i];
120-
try {
121-
for (var n in p) {
122-
copyProperty(n, p, obj);
115+
// copy top level properties from props to obj
116+
function mixin(obj, props) {
117+
obj = obj || {};
118+
try {
119+
Object.getOwnPropertyNames(props).forEach(function(n) {
120+
var pd = Object.getOwnPropertyDescriptor(props, n);
121+
if (pd) {
122+
Object.defineProperty(obj, n, pd);
123123
}
124-
} catch(x) {
125-
}
124+
});
125+
} catch(x) {
126126
}
127127
return obj;
128128
}
129129

130-
// copy property inName from inSource object to inTarget object
131-
function copyProperty(inName, inSource, inTarget) {
132-
var pd = getPropertyDescriptor(inSource, inName);
133-
Object.defineProperty(inTarget, inName, pd);
134-
}
135-
136-
// get property descriptor for inName on inObject, even if
137-
// inName exists on some link in inObject's prototype chain
138-
function getPropertyDescriptor(inObject, inName) {
139-
if (inObject) {
140-
var pd = Object.getOwnPropertyDescriptor(inObject, inName);
141-
return pd || getPropertyDescriptor(Object.getPrototypeOf(inObject), inName);
142-
}
143-
}
144-
145130
// exports
146131

147132
window.HTMLElementElement = HTMLElementElement;
148-
// TODO(sjmiles): completely ad-hoc, used by Polymer.register
149-
window.mixin = mixin;
150133

151134
})();

src/Parser.js

Lines changed: 14 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,30 @@
66

77
(function() {
88

9-
var IMPORT_LINK_TYPE = 'import';
9+
// import
10+
11+
var IMPORT_LINK_TYPE = window.HTMLImports ? HTMLImports.IMPORT_LINK_TYPE : 'none';
1012

1113
// highlander object for parsing a document tree
1214

13-
var componentParser = {
15+
var parser = {
1416
selectors: [
1517
'link[rel=' + IMPORT_LINK_TYPE + ']',
16-
'link[rel=stylesheet]',
17-
'script[src]',
18-
'script',
19-
'style',
2018
'element'
2119
],
2220
map: {
2321
link: 'parseLink',
24-
script: 'parseScript',
25-
element: 'parseElement',
26-
style: 'parseStyle'
22+
element: 'parseElement'
2723
},
2824
parse: function(inDocument) {
2925
if (!inDocument.__parsed) {
3026
// only parse once
3127
inDocument.__parsed = true;
3228
// all parsable elements in inDocument (depth-first pre-order traversal)
33-
var elts = inDocument.querySelectorAll(cp.selectors);
29+
var elts = inDocument.querySelectorAll(parser.selectors);
3430
// for each parsable node type, call the mapped parsing method
3531
forEach(elts, function(e) {
36-
//console.log(map[e.localName] + ":", path.nodeUrl(e));
37-
cp[cp.map[e.localName]](e);
32+
parser[parser.map[e.localName]](e);
3833
});
3934
// upgrade all upgradeable static elements, anything dynamically
4035
// created should be caught by observer
@@ -43,68 +38,31 @@ var componentParser = {
4338
CustomElements.observeDocument(inDocument);
4439
}
4540
},
46-
parseLink: function(inLinkElt) {
41+
parseLink: function(linkElt) {
4742
// imports
48-
if (isDocumentLink(inLinkElt)) {
49-
if (inLinkElt.content) {
50-
cp.parse(inLinkElt.content);
51-
}
52-
} else if (canAddToMainDoument(inLinkElt)) {
53-
document.head.appendChild(inLinkElt);
54-
}
55-
},
56-
parseScript: function(inScriptElt) {
57-
if (canAddToMainDoument(inScriptElt)) {
58-
// otherwise, evaluate now
59-
var code = inScriptElt.__resource || inScriptElt.textContent;
60-
if (code) {
61-
code += "\n//@ sourceURL=" + inScriptElt.__nodeUrl + "\n";
62-
eval.call(window, code);
63-
}
43+
if (isDocumentLink(linkElt)) {
44+
this.parseImport(linkElt);
6445
}
6546
},
66-
parseStyle: function(inStyleElt) {
67-
if (canAddToMainDoument(inStyleElt)) {
68-
document.head.appendChild(inStyleElt);
47+
parseImport: function(linkElt) {
48+
if (linkElt.content) {
49+
parser.parse(linkElt.content);
6950
}
7051
},
7152
parseElement: function(inElementElt) {
7253
new HTMLElementElement(inElementElt);
7354
}
7455
};
7556

76-
var cp = componentParser;
77-
78-
// nodes can be moved to the main document
79-
// if they are not in the main document, are not children of <element>
80-
// and are in a tree at parse time.
81-
function canAddToMainDoument(node) {
82-
return !inMainDocument(node)
83-
&& node.parentNode
84-
&& !isElementElementChild(node);
85-
}
86-
87-
function inMainDocument(inElt) {
88-
return inElt.ownerDocument === document ||
89-
// TODO(sjmiles): ShadowDOMPolyfill intrusion
90-
inElt.ownerDocument.impl === document;
91-
}
92-
9357
function isDocumentLink(inElt) {
9458
return (inElt.localName === 'link'
9559
&& inElt.getAttribute('rel') === IMPORT_LINK_TYPE);
9660
}
9761

98-
function isElementElementChild(inElt) {
99-
if (inElt.parentNode && inElt.parentNode.localName === 'element') {
100-
return true;
101-
}
102-
}
103-
10462
var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach);
10563

10664
// exports
10765

108-
CustomElements.parser = componentParser;
66+
CustomElements.parser = parser;
10967

11068
})();

src/boot.js

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,40 +7,42 @@
77

88
// bootstrap parsing
99

10-
// IE shim for CustomEvent
11-
if (typeof window.CustomEvent !== 'function') {
12-
window.CustomEvent = function(inType) {
13-
var e = document.createEvent('HTMLEvents');
14-
e.initEvent(inType, true, true);
15-
return e;
16-
};
17-
}
18-
1910
function bootstrap() {
2011
// go async so call stack can unwind
2112
setTimeout(function() {
2213
// parse document
2314
CustomElements.parser.parse(document);
24-
// set internal flag
15+
// one more pass before register is 'live'
16+
CustomElements.upgradeDocument(document);
17+
// set internal 'ready' flag, now document.register will trigger
18+
// synchronous upgrades
2519
CustomElements.ready = true;
20+
// capture blunt profiling data
2621
CustomElements.readyTime = new Date().getTime();
2722
if (window.HTMLImports) {
2823
CustomElements.elapsed = CustomElements.readyTime - HTMLImports.readyTime;
2924
}
30-
// notify system
25+
// notify the system that we are bootstrapped
3126
document.body.dispatchEvent(
3227
new CustomEvent('WebComponentsReady', {bubbles: true})
3328
);
3429
}, 0);
3530
}
3631

37-
// TODO(sjmiles): 'window' has no wrappability under ShadowDOM polyfill, so
38-
// we are forced to split into two versions
32+
// CustomEvent shim for IE
33+
if (typeof window.CustomEvent !== 'function') {
34+
window.CustomEvent = function(inType) {
35+
var e = document.createEvent('HTMLEvents');
36+
e.initEvent(inType, true, true);
37+
return e;
38+
};
39+
}
3940

40-
if (window.HTMLImports) {
41-
document.addEventListener('HTMLImportsLoaded', bootstrap);
41+
if (document.readyState === 'complete') {
42+
bootstrap();
4243
} else {
43-
window.addEventListener('load', bootstrap);
44+
var loadEvent = window.HTMLImports ? 'HTMLImportsLoaded' : 'DOMContentLoaded';
45+
window.addEventListener(loadEvent, bootstrap);
4446
}
4547

4648
})();

0 commit comments

Comments
 (0)