time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

main.js (3703B)


      1 /**
      2 * @license Apache-2.0
      3 *
      4 * Copyright (c) 2018 The Stdlib Authors.
      5 *
      6 * Licensed under the Apache License, Version 2.0 (the "License");
      7 * you may not use this file except in compliance with the License.
      8 * You may obtain a copy of the License at
      9 *
     10 *    http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing, software
     13 * distributed under the License is distributed on an "AS IS" BASIS,
     14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 * See the License for the specific language governing permissions and
     16 * limitations under the License.
     17 */
     18 
     19 'use strict';
     20 
     21 // MODULES //
     22 
     23 var MAX_SAFE_INTEGER = require( '@stdlib/constants/float64/max-safe-integer' );
     24 var isPositiveInteger = require( '@stdlib/assert/is-positive-integer' ).isPrimitive;
     25 var getOwnPropertyDescriptors = require( './../../property-descriptors' );
     26 var getOwnPropertySymbols = require( './../../property-symbols' );
     27 var getPrototypeOf = require( './../../get-prototype-of' );
     28 var objectKeys = require( './../../keys' );
     29 var defineProperty = require( './../../define-property' );
     30 var hasOwnProp = require( '@stdlib/assert/has-own-property' );
     31 
     32 
     33 // MAIN //
     34 
     35 /**
     36 * Returns an object's inherited property descriptors.
     37 *
     38 * ## Notes
     39 *
     40 * -   In contrast to the built-in `Object.getOwnPropertyDescriptors()`, this function returns an empty object if provided `undefined` or `null`, rather than throwing an error.
     41 *
     42 * @param {*} value - input object
     43 * @param {PositiveInteger} [level] - inheritance level
     44 * @throws {TypeError} second argument must be a positive integer
     45 * @returns {Object} inherited property descriptors
     46 *
     47 * @example
     48 * var desc = inheritedPropertyDescriptors( [] );
     49 * // returns {...}
     50 */
     51 function inheritedPropertyDescriptors( value, level ) { // eslint-disable-line id-length
     52 	var desc;
     53 	var keys;
     54 	var obj;
     55 	var tmp;
     56 	var N;
     57 	var n;
     58 	var i;
     59 
     60 	if ( arguments.length > 1 ) {
     61 		if ( !isPositiveInteger( level ) ) {
     62 			throw new TypeError( 'invalid argument. Second argument must be a positive integer. Value: `' + level + '`.' );
     63 		}
     64 		N = level;
     65 	} else {
     66 		N = MAX_SAFE_INTEGER;
     67 	}
     68 	if ( value === null || value === void 0 ) {
     69 		return {};
     70 	}
     71 	// Get the value's prototype:
     72 	obj = getPrototypeOf( value );
     73 
     74 	// Walk the prototype chain collecting all property descriptors...
     75 	desc = {};
     76 	n = 1;
     77 	while ( obj && n <= N ) {
     78 		tmp = getOwnPropertyDescriptors( obj );
     79 		keys = objectKeys( tmp );
     80 		for ( i = 0; i < keys.length; i++ ) {
     81 			// The first encountered property descriptor for a property name always takes precedence...
     82 			if ( !hasOwnProp( desc, keys[ i ] ) ) {
     83 				// The following is equivalent to `desc[ keys[i] ] = {...}`, but accounts for the possibility of a "poisoned" `Object` prototype (i.e., an `Object.prototype` having a property with a setter which throws).
     84 				defineProperty( desc, keys[ i ], {
     85 					'configurable': true,
     86 					'enumerable': true,
     87 					'writable': true,
     88 					'value': tmp[ keys[ i ] ]
     89 				});
     90 			}
     91 		}
     92 		keys = getOwnPropertySymbols( tmp );
     93 		for ( i = 0; i < keys.length; i++ ) {
     94 			// The first encountered property descriptor for a symbol property always takes precedence...
     95 			if ( !hasOwnProp( desc, keys[ i ] ) ) {
     96 				// The following is equivalent to `desc[ keys[i] ] = {...}`, but accounts for the possibility of a "poisoned" `Object` prototype (i.e., an `Object.prototype` having a property with a setter which throws).
     97 				defineProperty( desc, keys[ i ], {
     98 					'configurable': true,
     99 					'enumerable': true,
    100 					'writable': true,
    101 					'value': tmp[ keys[ i ] ]
    102 				});
    103 			}
    104 		}
    105 		obj = getPrototypeOf( obj );
    106 		n += 1;
    107 	}
    108 	return desc;
    109 }
    110 
    111 
    112 // EXPORTS //
    113 
    114 module.exports = inheritedPropertyDescriptors;