diff --git a/es5-shim.js b/es5-shim.js index ffc9a131..b851f71f 100644 --- a/es5-shim.js +++ b/es5-shim.js @@ -135,11 +135,22 @@ $Object.defineProperty(F, 'prototype', { value: sentinel, writable: false }); if ((new F()).toString !== toStringSentinel) { var $dP = $Object.defineProperty; + var $gOPD = $Object.getOwnPropertyDescriptor; defineProperties($Object, { defineProperty: function defineProperty(o, k, d) { var key = $String(k); - if (key === 'prototype' && 'writable' in d && 'value' in d) { - o[key] = d.value; // eslint-disable-line no-param-reassign + if (typeof o === 'function' && key === 'prototype') { + var desc = $gOPD(o, key); + if (desc.writable && !d.writable && 'value' in d) { + try { + o[key] = d.value; // eslint-disable-line no-param-reassign + } catch (e) { /**/ } + } + return $dP(o, key, { + configurable: 'configurable' in d ? d.configurable : desc.configurable, + enumerable: 'enumerable' in d ? d.enumerable : desc.enumerable, + writable: d.writable + }); } return $dP(o, key, d); } diff --git a/tests/spec/s-object.js b/tests/spec/s-object.js index 2b7e8c8f..6af28ebc 100644 --- a/tests/spec/s-object.js +++ b/tests/spec/s-object.js @@ -12,6 +12,7 @@ var supportsDescriptors = Object.defineProperty && (function () { return false; } }()); +var ifSupportsDescriptorsIt = supportsDescriptors ? it : xit; var ifWindowIt = typeof window === 'undefined' ? xit : it; var extensionsPreventible = typeof Object.preventExtensions === 'function' && (function () { var obj = {}; @@ -248,7 +249,7 @@ describe('Object', function () { }).not.toThrow(); }); - (supportsDescriptors ? it : xit)('allows setting a nonwritable prototype', function () { + ifSupportsDescriptorsIt('allows setting a nonwritable prototype', function () { var F = function () {}; expect(F.prototype).toEqual(Object.getOwnPropertyDescriptor(F, 'prototype').value); expect((new F()).toString).toEqual(Object.prototype.toString); @@ -264,6 +265,24 @@ describe('Object', function () { expect(F.prototype).toEqual(Object.getOwnPropertyDescriptor(F, 'prototype').value); expect((new F()).toString).toEqual(toStringSentinel); }); + + ifSupportsDescriptorsIt('properly makes a prototype non-writable', function () { + var O = { prototype: 1 }; + expect(O.prototype).toEqual(Object.getOwnPropertyDescriptor(O, 'prototype').value); + expect(O.prototype).toEqual(1); + + expect(function () { + Object.defineProperty(O, 'prototype', { writable: false, configurable: true }); + }).not.toThrow(); + + var sentinel = {}; + expect(function () { + Object.defineProperty(O, 'prototype', { value: sentinel }); + }).not.toThrow(); + + expect(O.prototype).toEqual(Object.getOwnPropertyDescriptor(O, 'prototype').value); + expect(O.prototype).toEqual(sentinel); + }); }); describe('.getOwnPropertyDescriptor()', function () {