time-to-botec

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

main.js (3486B)


      1 /**
      2 * @license Apache-2.0
      3 *
      4 * Copyright (c) 2019 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 isObject = require( '@stdlib/assert/is-object' );
     24 var isFunction = require( '@stdlib/assert/is-function' );
     25 var defineProperty = require( './../../define-property' );
     26 
     27 
     28 // MAIN //
     29 
     30 /**
     31 * Defines a memoized object property.
     32 *
     33 * @param {Object} obj - object on which to define the property
     34 * @param {(string|symbol)} prop - property name
     35 * @param {Object} desc - property descriptor
     36 * @param {boolean} [desc.configurable=false] - boolean indicating if the property descriptor can be changed and if the property can be deleted from the provided object
     37 * @param {boolean} [desc.enumerable=false] - boolean indicating if the property shows up when enumerating object properties
     38 * @param {boolean} [desc.writable=false] - boolean indicating if the value associated with the property can be changed with an assignment operator
     39 * @param {Function} desc.value - function whose return value will be memoized
     40 * @throws {TypeError} first argument must be an object
     41 * @throws {TypeError} third argument must be an object
     42 * @throws {TypeError} property descriptor `value` property must be a function
     43 *
     44 * @example
     45 * var obj = {};
     46 *
     47 * function foo() {
     48 *     return 'bar';
     49 * }
     50 *
     51 * defineMemoizedProperty( obj, 'foo', {
     52 *     'configurable': false,
     53 *     'enumerable': false,
     54 *     'writable': false,
     55 *     'value': foo
     56 * });
     57 *
     58 * var v = obj.foo;
     59 * // returns 'bar'
     60 */
     61 function defineMemoizedProperty( obj, prop, desc ) {
     62 	if ( !isObject( obj ) ) {
     63 		throw new TypeError( 'invalid argument. First argument must be an object. Value: `' + obj + '`.' );
     64 	}
     65 	if ( !isObject( desc ) ) {
     66 		throw new TypeError( 'invalid argument. Property descriptor must be an object. Value: `' + desc + '`.' );
     67 	}
     68 	if ( !isFunction( desc.value ) ) {
     69 		throw new TypeError( 'invalid argument. The `value` property of the property descriptor must be a function. Value: `' + desc.value + '`.' );
     70 	}
     71 	// Copy descriptor properties to a new data descriptor object:
     72 	desc = {
     73 		'configurable': ( desc.configurable === void 0 ) ? false : desc.configurable,
     74 		'enumerable': ( desc.enumerable === void 0 ) ? false : desc.enumerable,
     75 		'writable': ( desc.writable === void 0 ) ? false : desc.writable,
     76 		'value': desc.value
     77 	};
     78 
     79 	// Define a configurable (at least temporarily) accessor property:
     80 	defineProperty( obj, prop, {
     81 		'configurable': true,
     82 		'enumerable': desc.enumerable,
     83 		'get': getter,
     84 		'set': ( desc.writable ) ? memoize : void 0
     85 	});
     86 
     87 	/**
     88 	* Temporary get accessor.
     89 	*
     90 	* @private
     91 	* @returns {*} property value
     92 	*/
     93 	function getter() {
     94 		var value = desc.value.call( obj );
     95 		memoize( value );
     96 		return value;
     97 	}
     98 
     99 	/**
    100 	* Defines a memoized object property.
    101 	*
    102 	* @private
    103 	* @param {*} value - value to set
    104 	*/
    105 	function memoize( value ) {
    106 		desc.value = value;
    107 		defineProperty( obj, prop, desc );
    108 	}
    109 }
    110 
    111 
    112 // EXPORTS //
    113 
    114 module.exports = defineMemoizedProperty;