1
0
Fork 0

Provided a more accurate mechanism for detecting Object.defineProperty (tests in IE8 fixed)

closure/master
Mike Gerwitz 2011-03-07 09:03:03 -05:00
parent 522165fb6a
commit fbc58384b4
4 changed files with 53 additions and 30 deletions

View File

@ -35,13 +35,33 @@ var getset = ( Object.prototype.__defineGetter__ === undefined )
;
/**
* Whether we can actually define secure properties, or we need to fall back
* Whether we can actually define properties, or we need to fall back
*
* This check actually attempts to set a property and fails if there's an error.
* This is needed because IE8 has a broken implementation, yet still defines
* Object.defineProperty for use with DOM elements. Just another day in the life
* of a web developer.
*
* This test is only performed once, when the module is first loaded. Don't
* expect a performance hit from it.
*
* @type {boolean}
*/
var secure_fallback = ( Object.defineProperty instanceof Function )
? false
: true
;
var can_define_prop = ( function()
{
if ( typeof Object.defineProperty === 'function' )
{
try
{
// perform test, primarily for IE8
Object.defineProperty( {}, 'x', {} );
return true;
}
catch ( e ) {}
}
return false;
} )();
/**
@ -65,8 +85,8 @@ exports.freeze = function( obj )
/**
* Gets/sets whether the system needs to fall back to defining normal properties
* when a secure property is requested
* Gets/sets whether the system needs to fall back to defining properties in a
* normal manner when use of Object.defineProperty() is requested
*
* This will be set by default if the JS engine does not support the
* Object.defineProperty method from EcmaScript 5.
@ -75,14 +95,14 @@ exports.freeze = function( obj )
*
* @return {boolean|Object} current value if getter, self if setter
*/
exports.secureFallback = function( val )
exports.definePropertyFallback = function( val )
{
if ( val === undefined )
{
return secure_fallback;
return !can_define_prop;
}
secure_fallback = !!val;
can_define_prop = !val;
exports.defineSecureProp = getDefineSecureProp();
return exports;
@ -343,7 +363,7 @@ function getDefineSecureProp()
obj[ prop ] = value;
};
if ( secure_fallback )
if ( !can_define_prop )
{
return fallback;
}
@ -367,7 +387,7 @@ function getDefineSecureProp()
{
// let's not have this happen again, as repeatedly throwing
// exceptions will do nothing but slow down the system
exports.secureFallback( true );
exports.definePropertyFallback( true );
// if there's an error (ehem, IE8), fall back
fallback( obj, prop, value );

View File

@ -24,7 +24,8 @@
var common = require( './common' ),
assert = require( 'assert' ),
Interface = common.require( 'interface' )
Interface = common.require( 'interface' ),
util = common.require( 'util' )
;
@ -167,7 +168,7 @@ var common = require( './common' ),
;
// if we have getter/setter support, add those to the tests
if ( Object.defineProperty )
if ( !( util.definePropertyFallback() ) )
{
// getter
tries.push( function()

View File

@ -22,14 +22,9 @@
* @package test
*/
// no need to test getters/setters in browsers that do not support them
if ( !Object.defineProperty )
{
return;
}
var common = require( './common' ),
assert = require( 'assert' ),
util = common.require( 'util' ),
buildGetter = common.require( 'member_builder' ).buildGetter,
buildSetter = common.require( 'member_builder' ).buildSetter,
@ -44,6 +39,13 @@ var common = require( './common' ),
;
// no need to test getters/setters in browsers that do not support them
if ( util.definePropertyFallback() )
{
return;
}
function setUp()
{
// clear out the members for a fresh start

View File

@ -30,20 +30,20 @@ var obj = {},
val = 'bar';
var expected = ( ( Object.defineProperty instanceof Function ) ? false : true ),
fallback = util.secureFallback();
fallback = util.definePropertyFallback();
// IE 8 will fall back on first failure
if ( !expected && fallback )
{
try
{
util.secureFallback( false );
util.definePropertyFallback( false );
util.defineSecureProp( {}, 'foo', 1 );
// If the fallback was changed on us, then there was a problem (and this
// is likely IE8). Change the value we're expecting so our tests don't
// fail.
if ( util.secureFallback() === true )
if ( util.definePropertyFallback() === true )
{
expected = true;
}
@ -54,14 +54,14 @@ if ( !expected && fallback )
assert.equal(
expected,
fallback,
"util.secureFallback() returns whether defining a secure property is " +
"util.definePropertyFallback() returns whether defining a secure property is " +
"unsupported"
);
assert.equal(
util.secureFallback( fallback ),
util.definePropertyFallback( fallback ),
util,
"util.secureFallback() returns self when used as a setter"
"util.definePropertyFallback() returns self when used as a setter"
);
// perform secure property tests only if our parser supports it
@ -108,7 +108,7 @@ if ( fallback === false )
// be naughty so we can test the alternative implementation
util.secureFallback( true );
util.definePropertyFallback( true );
var obj2 = {},
val2 = 'baz';
@ -149,5 +149,5 @@ if ( fallback === false )
}
// restore in case the tests are not being run in separate processes
util.secureFallback( fallback );
util.definePropertyFallback( fallback );