diff --git a/gruntfile.js b/gruntfile.js
index 145c1e3913..ec1a24ec5e 100644
--- a/gruntfile.js
+++ b/gruntfile.js
@@ -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) {
@@ -140,7 +141,10 @@ module.exports = function(grunt) {
'../CustomElements',
'../PointerEvents',
'../PointerGestures',
- '../mdv'
+ '../polymer-expressions',
+ '../observe-js',
+ '../NodeBind',
+ '../TemplateInstances'
]
},
dest: 'build.log',
diff --git a/polymer.js b/polymer.js
index 3f8574ff47..42bb26986c 100644
--- a/polymer.js
+++ b/polymer.js
@@ -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) {
@@ -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('');
}
-document.write('');
+document.write('');
})();
diff --git a/src/declaration/polymer-element.js b/src/declaration/polymer-element.js
index 9bb69e7590..fadc396efc 100644
--- a/src/declaration/polymer-element.js
+++ b/src/declaration/polymer-element.js
@@ -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 + ']');
@@ -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 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:
- 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');
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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() {
@@ -280,6 +129,8 @@
}
});
+ // semi-pluggable APIs
+ // TODO(sjmiles): should be fully pluggable
Object.keys(apis).forEach(function(n) {
extend(prototype, apis[n]);
});
@@ -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()`
diff --git a/src/declaration/prototype.js b/src/declaration/prototype.js
new file mode 100644
index 0000000000..0b7ac527b2
--- /dev/null
+++ b/src/declaration/prototype.js
@@ -0,0 +1,100 @@
+/*
+ * 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) {
+
+ // imports
+
+ var api = scope.api;
+ var isBase = scope.isBase;
+ var extend = scope.extend;
+
+ // returns a prototype that chains to 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 (isBase(ancestor)) {
+ ancestor.__proto__ = Object.getPrototypeOf(ancestor);
+ }
+ }
+ }
+
+ // declarative implementation:
+
+ var prototype = generatePrototype();
+
+ // prototype api
+
+ var prototype = {
+ // 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
+ this.addNamedApi(prototype, name);
+ // x-platform fixups
+ ensurePrototypeTraversal(prototype);
+ return prototype;
+ },
+ // 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(api.instance).forEach(function(n) {
+ extend(prototype, 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, scope.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);
+ }
+ };
+
+ // exports
+
+ api.declaration.prototype = prototype;
+
+})(Polymer);
diff --git a/src/instance/base.js b/src/instance/base.js
index 09289253f7..5ee15a26cf 100644
--- a/src/instance/base.js
+++ b/src/instance/base.js
@@ -10,7 +10,11 @@
job: Polymer.job,
super: Polymer.super,
// user entry point for constructor-like initialization
+ created: function() {
+ },
+ // TODO(sorvell): temporary BC
ready: function() {
+
},
// TODO(sjmiles): temporary BC
readyCallback: function() {
@@ -40,7 +44,9 @@
// when polyfilling Object.observe
//this.asyncUnbindAll();
// user initialization
+ // TODO(sorvell): bc
this.ready();
+ this.created();
},
insertedCallback: function() {
this._enteredDocumentCallback();
diff --git a/src/instance/mdv.js b/src/instance/mdv.js
index 59f42e0d58..01b76552dd 100644
--- a/src/instance/mdv.js
+++ b/src/instance/mdv.js
@@ -11,7 +11,7 @@
// use an MDV syntax
- var mdv_syntax = new ExpressionSyntax();
+ var mdv_syntax = new PolymerExpressions();
// element api supporting mdv
diff --git a/test/html/bind-object-repeat.html b/test/html/bind-object-repeat.html
index f083a1437f..a908a2d2ba 100644
--- a/test/html/bind-object-repeat.html
+++ b/test/html/bind-object-repeat.html
@@ -46,26 +46,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Hello Lighter World []
+
+
+
+
+
+
+