diff --git a/src/wrappers.js b/src/wrappers.js index 7e89655..f3a2bb3 100644 --- a/src/wrappers.js +++ b/src/wrappers.js @@ -30,16 +30,19 @@ window.ShadowDOMPolyfill = {}; throw new Error('Assertion failed'); }; + var defineProperty = Object.defineProperty; + var getOwnPropertyNames = Object.getOwnPropertyNames; + var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + function mixin(to, from) { - Object.getOwnPropertyNames(from).forEach(function(name) { - Object.defineProperty(to, name, - Object.getOwnPropertyDescriptor(from, name)); + getOwnPropertyNames(from).forEach(function(name) { + defineProperty(to, name, getOwnPropertyDescriptor(from, name)); }); return to; }; function mixinStatics(to, from) { - Object.getOwnPropertyNames(from).forEach(function(name) { + getOwnPropertyNames(from).forEach(function(name) { switch (name) { case 'arguments': case 'caller': @@ -49,8 +52,7 @@ window.ShadowDOMPolyfill = {}; case 'toString': return; } - Object.defineProperty(to, name, - Object.getOwnPropertyDescriptor(from, name)); + defineProperty(to, name, getOwnPropertyDescriptor(from, name)); }); return to; }; @@ -65,7 +67,7 @@ window.ShadowDOMPolyfill = {}; // Mozilla's old DOM bindings are bretty busted: // https://bugzilla.mozilla.org/show_bug.cgi?id=855844 // Make sure they are create before we start modifying things. - Object.getOwnPropertyNames(window); + getOwnPropertyNames(window); function getWrapperConstructor(node) { var nativePrototype = node.__proto__ || Object.getPrototypeOf(node); @@ -128,7 +130,7 @@ window.ShadowDOMPolyfill = {}; } function installProperty(source, target, allowMethod) { - Object.getOwnPropertyNames(source).forEach(function(name) { + getOwnPropertyNames(source).forEach(function(name) { if (name in target) return; @@ -138,7 +140,7 @@ window.ShadowDOMPolyfill = {}; } var descriptor; try { - descriptor = Object.getOwnPropertyDescriptor(source, name); + descriptor = getOwnPropertyDescriptor(source, name); } catch (ex) { // JSC and V8 both use data properties instead of accessors which can // cause getting the property desciptor to throw an exception. @@ -164,7 +166,7 @@ window.ShadowDOMPolyfill = {}; setter = getSetter(name); } - Object.defineProperty(target, name, { + defineProperty(target, name, { get: getter, set: setter, configurable: descriptor.configurable, @@ -195,6 +197,12 @@ window.ShadowDOMPolyfill = {}; addForwardingProperties(nativePrototype, wrapperPrototype); if (opt_instance) registerInstanceProperties(wrapperPrototype, opt_instance); + defineProperty(wrapperPrototype, 'constructor', { + value: wrapperConstructor, + configurable: true, + enumerable: false, + writable: true + }); } function isWrapperFor(wrapperConstructor, nativeConstructor) { @@ -205,11 +213,7 @@ window.ShadowDOMPolyfill = {}; /** * Creates a generic wrapper constructor based on |object| and its * constructor. - * Sometimes the constructor does not have an associated instance - * (CharacterData for example). In that case you can pass the constructor that - * you want to map the object to using |opt_nativeConstructor|. * @param {Node} object - * @param {Function=} opt_nativeConstructor * @return {Function} The generated constructor. */ function registerObject(object) { @@ -322,7 +326,7 @@ window.ShadowDOMPolyfill = {}; } function defineGetter(constructor, name, getter) { - Object.defineProperty(constructor.prototype, name, { + defineProperty(constructor.prototype, name, { get: getter, configurable: true, enumerable: true diff --git a/test/js/wrappers.js b/test/js/wrappers.js index 5c6957b..519d4dd 100644 --- a/test/js/wrappers.js +++ b/test/js/wrappers.js @@ -17,6 +17,13 @@ suite('Wrapper creation', function() { assert.isTrue(Object.getPrototypeOf(br).hasOwnProperty('clear')); }); + test('HTMLUnknownElement constructor', function() { + var element = document.createElement('unknownelement'); + assert.instanceOf(element, HTMLUnknownElement); + assert.equal(Object.getPrototypeOf(element), HTMLUnknownElement.prototype); + assert.equal(Object.getPrototypeOf(element).constructor, HTMLUnknownElement); + }); + Object.keys(knownElements).forEach(function(tagName) { test(tagName, function() { var constructor = window[knownElements[tagName]]; @@ -26,6 +33,7 @@ suite('Wrapper creation', function() { var element = document.createElement(tagName); assert.instanceOf(element, constructor); assert.equal(Object.getPrototypeOf(element), constructor.prototype); + assert.equal(Object.getPrototypeOf(element).constructor, constructor); }); });