Skip to content

Commit

Permalink
Merge pull request #241 from Polymer/master
Browse files Browse the repository at this point in the history
8/15 master -> stable
  • Loading branch information
dfreedm committed Aug 15, 2013
2 parents 12fb68a + 38ce9b4 commit a32f21b
Show file tree
Hide file tree
Showing 29 changed files with 423 additions and 300 deletions.
6 changes: 5 additions & 1 deletion gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module.exports = function(grunt) {
"declaration/events.js",
"declaration/properties.js",
"declaration/attributes.js",
"declaration/prototype.js",
"declaration/polymer-element.js",
"deprecated.js"
].map(function(n) {
Expand Down Expand Up @@ -140,7 +141,10 @@ module.exports = function(grunt) {
'../CustomElements',
'../PointerEvents',
'../PointerGestures',
'../mdv'
'../polymer-expressions',
'../observe-js',
'../NodeBind',
'../TemplateInstances'
]
},
dest: 'build.log',
Expand Down
5 changes: 3 additions & 2 deletions polymer.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ var modules = [
"declaration/events.js",
"declaration/properties.js",
"declaration/attributes.js",
"declaration/prototype.js",
"declaration/polymer-element.js",
"deprecated.js"
].map(function(n) {
Expand All @@ -50,10 +51,10 @@ var script = document.querySelector('script[src*="' + thisFile + '"]');
var src = script.attributes.src.value;
var basePath = src.slice(0, src.indexOf(thisFile));

if (!window.Loader) {
if (!window.PolymerLoader) {
var path = basePath + 'tools/loader/loader.js';
document.write('<script src="' + path + '"></script>');
}
document.write('<script>Loader.load("' + scopeName + '")</script>');
document.write('<script>PolymerLoader.load("' + scopeName + '")</script>');

})();
241 changes: 73 additions & 168 deletions src/declaration/polymer-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,11 @@

// imports

var extend = Polymer.extend;
var extend = scope.extend;
var apis = scope.api.declaration;

// imperative implementation: Polymer()

// maps tag names to prototypes
var prototypesByName = {};

function getRegisteredPrototype(name) {
return prototypesByName[name];
}

// elements waiting for prototype, by name
var waitPrototype = {};

// specify an 'own' prototype for tag `name`
function element(name, prototype) {
//console.log('registering [' + name + ']');
Expand All @@ -31,71 +21,9 @@
notifyPrototype(name);
}

function notifyPrototype(name) {
if (waitPrototype[name]) {
waitPrototype[name].registerWhenReady();
delete waitPrototype[name];
}
}

// elements waiting for super, by name
var waitSuper = {};

function notifySuper(name) {
registered[name] = true;
var waiting = waitSuper[name];
if (waiting) {
waiting.forEach(function(w) {
w.registerWhenReady();
});
delete waitSuper[name];
}
}

// track document.register'ed tag names

var registered = {};

function isRegistered(name) {
return registered[name];
}

// returns a prototype that chains to <tag> or HTMLElement
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 desugaring.
function ensurePrototypeTraversal(prototype) {
if (!Object.__proto__) {
var ancestor = Object.getPrototypeOf(prototype);
prototype.__proto__ = ancestor;
if (scope.isBase(ancestor)) {
ancestor.__proto__ = Object.getPrototypeOf(ancestor);
}
}
}

function whenImportsLoaded(doThis) {
if (window.HTMLImports && !HTMLImports.readyTime) {
addEventListener('HTMLImportsLoaded', doThis);
} else {
doThis();
}
}

// declarative implementation: <polymer-element>

var prototype = generatePrototype();

extend(prototype, {
// TODO(sjmiles): temporary BC
readyCallback: function() {
this.createdCallback();
},
var prototype = extend(Object.create(HTMLElement.prototype), {
createdCallback: function() {
// fetch the element name
this.name = this.getAttribute('name');
Expand All @@ -108,48 +36,22 @@
if (!getRegisteredPrototype(name)) {
// then wait for a prototype
waitPrototype[name] = this;
// TODO(sjmiles): 'noscript' gambit is mutually exclusive
// with 'async' gambit below
//
// if explicitly marked as 'noscript'
if (this.hasAttribute('noscript')) {
// go async to allow children to parse
setTimeout(function() {
// register with the default prototype
element(name, null);
}, 0);
}
// TODO(sjmiles): 'async' gambit is deemed too dangerous
// because it changes the timing of noscript elements
// in import from 'timeout 0' to 'HTMLImportsReady'
/*
// if we are not explicitly async...
if (!this.hasAttribute('async')) {
// then we expect the script to be registered
// by end of microtask(-ish) and can otherwise
// consider this element to have no script
//
// TODO(sjmiles):
// we have to wait for end-of-microtask because
// native CE upgrades polymer-element (any custom
// element, really) *before* it's children are
// parsed, and it's common for the script to
// exist as a child of the polymer-element
//
// additionally, there is a massive asynchrony
// between parsing HTML in imports and executing
// script that foils the end of microtask gambit
// Waiting on HTMLImportsLoaded signal solves
// both timing problems for imports loaded
// at startup under the import polyfill
whenImportsLoaded(function() {
if (!getRegisteredPrototype(name)) {
console.warn('giving up waiting for script for [' + name + ']');
element(name, null);
}
});
// TODO(sorvell): CustomElements polyfill awareness:
// noscript elements should upgrade in logical order
// script injection ensures this under native custom elements;
// under imports + ce polyfill, scripts run before upgrades
// dependencies should be ready at upgrade time so register
// prototype at this time.
if (window.CustomElements && !CustomElements.useNative) {
element(name);
} else {
var script = document.createElement('script');
script.textContent = 'Polymer(\'' + name + '\');';
this.appendChild(script);
}
}
*/
return;
}
// fetch our extendee name
Expand All @@ -162,7 +64,7 @@
return;
}
}
// TODO(sjmiles): HTMLImports polyfill awareness
// TODO(sjmiles): HTMLImports polyfill awareness:
// elements in the main document are likely to parse
// in advance of elements in imports because the
// polyfill parser is simulated
Expand All @@ -177,7 +79,6 @@
}
},
register: function(name, extendee) {
//console.log('register', name, extendee);
// build prototype combining extendee, Polymer base, and named api
this.prototype = this.generateCustomPrototype(name, extendee);
// backref
Expand All @@ -188,7 +89,6 @@
// 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
Expand Down Expand Up @@ -219,57 +119,6 @@
// cache the list of custom prototype names for faster reflection
this.cacheProperties();
},
// prototype marshaling
// build prototype combining extendee, Polymer base, and named api
generateCustomPrototype: function (name, extnds) {
// basal prototype
var prototype = this.generateBasePrototype(extnds);
// mixin registered custom api
return this.addNamedApi(prototype, name);
},
// build prototype combining extendee, Polymer base, and named api
generateBasePrototype: function(extnds) {
// create a prototype based on tag-name extension
var prototype = generatePrototype(extnds);
// insert base api in inheritance chain (if needed)
return this.ensureBaseApi(prototype);
},
// install Polymer instance api into prototype chain, as needed
ensureBaseApi: function(prototype) {
if (!prototype.PolymerBase) {
Object.keys(scope.api.instance).forEach(function(n) {
extend(prototype, scope.api.instance[n]);
});
prototype = Object.create(prototype);
}
// inherit publishing meta-data
this.inheritAttributesObjects(prototype);
// inherit event delegates
this.inheritDelegates(prototype);
// return buffed-up prototype
return prototype;
},
// mix api registered to 'name' into 'prototype'
addNamedApi: function(prototype, name) {
// combine custom api into prototype
return extend(prototype, getRegisteredPrototype(name));
},
// make a fresh object that inherits from a prototype object
inheritObject: function(prototype, name) {
// copy inherited properties onto a new object
prototype[name] = extend({}, Object.getPrototypeOf(prototype)[name]);
},
// register 'prototype' to custom element 'name', store constructor
registerPrototype: function(name) {
// register the custom type
this.ctor = document.register(name, {
prototype: this.prototype
});
// constructor shenanigans
this.prototype.constructor = this.ctor;
// register the prototype with HTMLElement for name lookup
HTMLElement.register(name, this.prototype);
},
// if a named constructor is requested in element, map a reference
// to the constructor to the given symbol
publishConstructor: function() {
Expand All @@ -280,6 +129,8 @@
}
});

// semi-pluggable APIs
// TODO(sjmiles): should be fully pluggable
Object.keys(apis).forEach(function(n) {
extend(prototype, apis[n]);
});
Expand All @@ -288,7 +139,61 @@

document.register('polymer-element', {prototype: prototype});

// namespace shenanigans so we can expose our scope on the registration function
// utility and bookkeeping

// maps tag names to prototypes
var prototypesByName = {};

function getRegisteredPrototype(name) {
return prototypesByName[name];
}

// elements waiting for prototype, by name
var waitPrototype = {};

function notifyPrototype(name) {
if (waitPrototype[name]) {
waitPrototype[name].registerWhenReady();
delete waitPrototype[name];
}
}

// elements waiting for super, by name
var waitSuper = {};

function notifySuper(name) {
registered[name] = true;
var waiting = waitSuper[name];
if (waiting) {
waiting.forEach(function(w) {
w.registerWhenReady();
});
delete waitSuper[name];
}
}

// track document.register'ed tag names

var registered = {};

function isRegistered(name) {
return registered[name];
}

function whenImportsLoaded(doThis) {
if (window.HTMLImports && !HTMLImports.readyTime) {
addEventListener('HTMLImportsLoaded', doThis);
} else {
doThis();
}
}

// exports

scope.getRegisteredPrototype = getRegisteredPrototype;

// namespace shenanigans so we can expose our scope on the registration
// function

// TODO(sjmiles): find a way to do this that is less terrible
// copy window.Polymer properties onto `element()`
Expand Down
Loading

0 comments on commit a32f21b

Please sign in to comment.