Skip to content

Commit

Permalink
fix(browser): make Object.defineProperty patch safer (angular#392)
Browse files Browse the repository at this point in the history
  • Loading branch information
marclaval authored and mhevery committed Aug 11, 2016
1 parent 571a4c7 commit 597c634
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 2 deletions.
25 changes: 23 additions & 2 deletions lib/browser/define-property.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ export function propertyPatch() {
if (isUnconfigurable(obj, prop)) {
throw new TypeError('Cannot assign to read only property \'' + prop + '\' of ' + obj);
}
const originalConfigurableFlag = desc.configurable;
if (prop !== 'prototype') {
desc = rewriteDescriptor(obj, prop, desc);
}
return _defineProperty(obj, prop, desc);
return _tryDefineProperty(obj, prop, desc, originalConfigurableFlag);
};

Object.defineProperties = function (obj, props) {
Expand Down Expand Up @@ -46,8 +47,9 @@ export function propertyPatch() {
};

export function _redefineProperty(obj, prop, desc) {
const originalConfigurableFlag = desc.configurable;
desc = rewriteDescriptor(obj, prop, desc);
return _defineProperty(obj, prop, desc);
return _tryDefineProperty(obj, prop, desc, originalConfigurableFlag);
};

function isUnconfigurable (obj, prop) {
Expand All @@ -65,4 +67,23 @@ function rewriteDescriptor (obj, prop, desc) {
return desc;
}

function _tryDefineProperty (obj, prop, desc, originalConfigurableFlag) {
try {
return _defineProperty(obj, prop, desc);
}
catch(e) {
if (desc.configurable) {
// In case of errors, when the configurable flag was likely set by rewriteDescriptor(), let's retry with the original flag value
if (typeof originalConfigurableFlag == 'undefined') {
delete desc.configurable;
} else {
desc.configurable = originalConfigurableFlag;
}
return _defineProperty(obj, prop, desc);
} else {
throw e;
}
}
}


8 changes: 8 additions & 0 deletions test/browser/define-property.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
describe('defineProperty', function () {

it('should not throw when defining length on an array', function () {
var someArray = [];
expect(() => Object.defineProperty(someArray, 'length', {value: 2, writable: false})).not.toThrow();
});

});
1 change: 1 addition & 0 deletions test/browser_entry_point.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import './test-env-setup';
// List all tests here:
import './common_tests';
import './browser/browser.spec';
import './browser/define-property.spec';
import './browser/element.spec';
import './browser/FileReader.spec';
import './browser/HTMLImports.spec';
Expand Down

0 comments on commit 597c634

Please sign in to comment.