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

Unified Diff: pkg/custom_element/lib/custom-elements.debug.js

Issue 23190026: Type extension support in polyfill. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 4 months 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 | « no previous file | pkg/custom_element/lib/custom-elements.min.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/custom_element/lib/custom-elements.debug.js
diff --git a/pkg/custom_element/lib/custom-elements.debug.js b/pkg/custom_element/lib/custom-elements.debug.js
index 400730bea18f9f5335e2fc5d818fb82ccaa94d43..be0a36032bbe1c5743357070633f9280a8a1d192 100644
--- a/pkg/custom_element/lib/custom-elements.debug.js
+++ b/pkg/custom_element/lib/custom-elements.debug.js
@@ -1045,23 +1045,23 @@ if (useNative) {
*
* When a registered element is created, a `readyCallback` method is called
* in the scope of the element. The `readyCallback` method can be specified on
- * either `inOptions.prototype` or `inOptions.lifecycle` with the latter taking
+ * either `options.prototype` or `options.lifecycle` with the latter taking
* precedence.
*
* @method register
- * @param {String} inName The tag name to register. Must include a dash ('-'),
+ * @param {String} name The tag name to register. Must include a dash ('-'),
* for example 'x-component'.
- * @param {Object} inOptions
- * @param {String} [inOptions.extends]
+ * @param {Object} options
+ * @param {String} [options.extends]
* (_off spec_) Tag name of an element to extend (or blank for a new
* element). This parameter is not part of the specification, but instead
* is a hint for the polyfill because the extendee is difficult to infer.
* Remember that the input prototype must chain to the extended element's
* prototype (or HTMLElement.prototype) regardless of the value of
* `extends`.
- * @param {Object} inOptions.prototype The prototype to use for the new
+ * @param {Object} options.prototype The prototype to use for the new
* element. The prototype must inherit from HTMLElement.
- * @param {Object} [inOptions.lifecycle]
+ * @param {Object} [options.lifecycle]
* Callbacks that fire at important phases in the life of the custom
* element.
*
@@ -1078,18 +1078,23 @@ if (useNative) {
* });
* @return {Function} Constructor for the newly registered type.
*/
- function register(inName, inOptions) {
- //console.warn('document.register("' + inName + '", ', inOptions, ')');
+ function register(name, options) {
+ //console.warn('document.register("' + name + '", ', options, ')');
// construct a defintion out of options
- // TODO(sjmiles): probably should clone inOptions instead of mutating it
- var definition = inOptions || {};
- if (!inName) {
+ // TODO(sjmiles): probably should clone options instead of mutating it
+ var definition = options || {};
+ if (!name) {
// TODO(sjmiles): replace with more appropriate error (EricB can probably
// offer guidance)
- throw new Error('Name argument must not be empty');
+ throw new Error('document.register: first argument `name` must not be empty');
+ }
+ if (name.indexOf('-') < 0) {
+ // TODO(sjmiles): replace with more appropriate error (EricB can probably
+ // offer guidance)
+ throw new Error('document.register: first argument `name` must contain a dash (\'-\'). Argument was \'' + String(name) + '\'.');
}
// record name
- definition.name = inName;
+ definition.name = name;
// must have a prototype, default to an extension of HTMLElement
// TODO(sjmiles): probably should throw if no prototype, check spec
if (!definition.prototype) {
@@ -1112,7 +1117,7 @@ if (useNative) {
// overrides to implement attributeChanged callback
overrideAttributeApi(definition.prototype);
// 7.1.5: Register the DEFINITION with DOCUMENT
- registerDefinition(inName, definition);
+ registerDefinition(name, definition);
// 7.1.7. Run custom element constructor generation algorithm with PROTOTYPE
// 7.1.8. Return the output of the previous step.
definition.ctor = generateConstructor(definition);
@@ -1127,40 +1132,40 @@ if (useNative) {
return definition.ctor;
}
- function ancestry(inExtends) {
- var extendee = registry[inExtends];
+ function ancestry(extnds) {
+ var extendee = registry[extnds];
if (extendee) {
return ancestry(extendee.extends).concat([extendee]);
}
return [];
}
- function resolveTagName(inDefinition) {
+ function resolveTagName(definition) {
// if we are explicitly extending something, that thing is our
// baseTag, unless it represents a custom component
- var baseTag = inDefinition.extends;
+ var baseTag = definition.extends;
// if our ancestry includes custom components, we only have a
// baseTag if one of them does
- for (var i=0, a; (a=inDefinition.ancestry[i]); i++) {
+ for (var i=0, a; (a=definition.ancestry[i]); i++) {
baseTag = a.is && a.tag;
}
// our tag is our baseTag, if it exists, and otherwise just our name
- inDefinition.tag = baseTag || inDefinition.name;
+ definition.tag = baseTag || definition.name;
if (baseTag) {
// if there is a base tag, use secondary 'is' specifier
- inDefinition.is = inDefinition.name;
+ definition.is = definition.name;
}
}
- function resolvePrototypeChain(inDefinition) {
+ function resolvePrototypeChain(definition) {
// if we don't support __proto__ we need to locate the native level
// prototype for precise mixing in
if (!Object.__proto__) {
// default prototype
var native = HTMLElement.prototype;
// work out prototype when using type-extension
- if (inDefinition.is) {
- var inst = document.createElement(inDefinition.tag);
+ if (definition.is) {
+ var inst = document.createElement(definition.tag);
native = Object.getPrototypeOf(inst);
}
// ensure __proto__ reference is installed at each point on the prototype
@@ -1168,7 +1173,7 @@ if (useNative) {
// NOTE: On platforms without __proto__, a mixin strategy is used instead
// of prototype swizzling. In this case, this generated __proto__ provides
// limited support for prototype traversal.
- var proto = inDefinition.prototype, ancestor;
+ var proto = definition.prototype, ancestor;
while (proto && (proto !== native)) {
var ancestor = Object.getPrototypeOf(proto);
proto.__proto__ = ancestor;
@@ -1176,49 +1181,49 @@ if (useNative) {
}
}
// cache this in case of mixin
- inDefinition.native = native;
+ definition.native = native;
}
// SECTION 4
- function instantiate(inDefinition) {
+ function instantiate(definition) {
// 4.a.1. Create a new object that implements PROTOTYPE
// 4.a.2. Let ELEMENT by this new object
//
// the custom element instantiation algorithm must also ensure that the
// output is a valid DOM element with the proper wrapper in place.
//
- return upgrade(domCreateElement(inDefinition.tag), inDefinition);
+ return upgrade(domCreateElement(definition.tag), definition);
}
- function upgrade(inElement, inDefinition) {
+ function upgrade(element, definition) {
// some definitions specify an 'is' attribute
- if (inDefinition.is) {
- inElement.setAttribute('is', inDefinition.is);
+ if (definition.is) {
+ element.setAttribute('is', definition.is);
}
- // make 'element' implement inDefinition.prototype
- implement(inElement, inDefinition);
+ // make 'element' implement definition.prototype
+ implement(element, definition);
// flag as upgraded
- inElement.__upgraded__ = true;
- // there should never be a shadow root on inElement at this point
+ element.__upgraded__ = true;
+ // there should never be a shadow root on element at this point
// we require child nodes be upgraded before `created`
- scope.upgradeSubtree(inElement);
+ scope.upgradeSubtree(element);
// lifecycle management
- created(inElement);
+ created(element);
// OUTPUT
- return inElement;
+ return element;
}
- function implement(inElement, inDefinition) {
+ function implement(element, definition) {
// prototype swizzling is best
if (Object.__proto__) {
- inElement.__proto__ = inDefinition.prototype;
+ element.__proto__ = definition.prototype;
} else {
// where above we can re-acquire inPrototype via
// getPrototypeOf(Element), we cannot do so when
// we use mixin, so we install a magic reference
- customMixin(inElement, inDefinition.prototype, inDefinition.native);
- inElement.__proto__ = inDefinition.prototype;
+ customMixin(element, definition.prototype, definition.native);
+ element.__proto__ = definition.prototype;
}
}
@@ -1246,10 +1251,10 @@ if (useNative) {
}
}
- function created(inElement) {
+ function created(element) {
// invoke createdCallback
- if (inElement.createdCallback) {
- inElement.createdCallback();
+ if (element.createdCallback) {
+ element.createdCallback();
}
}
@@ -1282,34 +1287,55 @@ if (useNative) {
var registry = {};
- function registerDefinition(inName, inDefinition) {
- if (registry[inName]) {
- throw new Error('Cannot register a tag more than once');
+ function registerDefinition(name, definition) {
+ if (registry[name]) {
+ throw new Error('a type with that name is already registered.');
}
- registry[inName] = inDefinition;
+ registry[name] = definition;
}
- function generateConstructor(inDefinition) {
+ function generateConstructor(definition) {
return function() {
- return instantiate(inDefinition);
+ return instantiate(definition);
};
}
function createElement(tag, typeExtension) {
- // TODO(sjmiles): ignore 'tag' when using 'typeExtension', we could
- // error check it, or perhaps there should only ever be one argument
var definition = registry[typeExtension || tag];
if (definition) {
- return new definition.ctor();
+ if (tag == definition.tag && typeExtension == definition.is) {
+ return new definition.ctor();
+ }
+ // Handle empty string for type extension.
+ if (!typeExtension && !definition.is) {
+ return new definition.ctor();
+ }
}
- return domCreateElement(tag);
+
+ if (typeExtension) {
+ var element = createElement(tag);
+ element.setAttribute('is', typeExtension);
+ return element;
+ }
+ var element = domCreateElement(tag);
+ // Custom tags should be HTMLElements even if not upgraded.
+ if (tag.indexOf('-') >= 0) {
+ implement(element, HTMLElement);
+ }
+ return element;
}
- function upgradeElement(inElement) {
- if (!inElement.__upgraded__ && (inElement.nodeType === Node.ELEMENT_NODE)) {
- var type = inElement.getAttribute('is') || inElement.localName;
- var definition = registry[type];
- return definition && upgrade(inElement, definition);
+ function upgradeElement(element) {
+ if (!element.__upgraded__ && (element.nodeType === Node.ELEMENT_NODE)) {
+ var is = element.getAttribute('is');
+ var definition = registry[is || element.localName];
+ if (definition) {
+ if (is && definition.tag == element.localName) {
+ return upgrade(element, definition);
+ } else if (!is && !definition.extends) {
+ return upgrade(element, definition);
+ }
+ }
}
}
@@ -1345,7 +1371,7 @@ if (useNative) {
* if it matches no registered custom tag name.
*
* @method ugprade
- * @param {Element} inElement The element to upgrade.
+ * @param {Element} element The element to upgrade.
* @return {Element} The upgraded element.
*/
scope.upgrade = upgradeElement;
« no previous file with comments | « no previous file | pkg/custom_element/lib/custom-elements.min.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698