Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8/15 master -> stable #241

Merged
merged 16 commits into from
Aug 15, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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