Skip to content

Commit

Permalink
validateOptionsOnValidateValue in validator -> validateOptions option,
Browse files Browse the repository at this point in the history
  • Loading branch information
zepumph committed Sep 20, 2019
1 parent f9d8019 commit f73877e
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 33 deletions.
14 changes: 4 additions & 10 deletions js/Action.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ define( require => {
const ValidatorDef = require( 'AXON/ValidatorDef' );

// constants
const VALIDATE_OPTIONS_FALSE = { validateOptions: false };

// Simulations have thousands of Emitters, so we re-use objects where possible.
const EMPTY_ARRAY = [];
assert && Object.freeze( EMPTY_ARRAY );
Expand Down Expand Up @@ -122,9 +124,6 @@ define( require => {
for ( let i = 0; i < parameters.length; i++ ) {
const parameter = parameters[ i ]; // metadata about a single parameter

assert && assert( parameter.validateOptionsOnValidateValue === undefined,
'Action sets its own validateOptionsOnValidateValue for each argument type'
);
assert && assert( Object.getPrototypeOf( parameter ) === Object.prototype,
'Extra prototype on parameter object is a code smell' );

Expand All @@ -147,11 +146,6 @@ define( require => {
assert && assert( PARAMETER_KEYS.includes( key ), 'unrecognized parameter key: ' + key );
}

// TODO: is this taking up too much memory? Does this create too much garbage? https://github.com/phetsims/axon/issues/257
parameters[ i ] = _.extend( {
validateOptionsOnValidateValue: false
}, parameter );

// Changing after construction indicates a logic error.
assert && Object.freeze( parameters[ i ] );

Expand Down Expand Up @@ -229,11 +223,11 @@ define( require => {
);
for ( let i = 0; i < this._parameters.length; i++ ) {
const parameter = this._parameters[ i ];
validate( arguments[ i ], parameter );
validate( arguments[ i ], parameter, VALIDATE_OPTIONS_FALSE );

// valueType overrides the phetioType validator so we don't use that one if there is a valueType
if ( parameter.phetioType && !this._parameters.valueType ) {
validate( arguments[ i ], parameter.phetioType.validator );
validate( arguments[ i ], parameter.phetioType.validator, VALIDATE_OPTIONS_FALSE );
}
}
}
Expand Down
9 changes: 4 additions & 5 deletions js/Property.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ define( require => {
const validate = require( 'AXON/validate' );
const ValidatorDef = require( 'AXON/ValidatorDef' );

// constants
const VALIDATE_OPTIONS_FALSE = { validateOptions: false };

// variables
let globalId = 0; // autoincremented for unique IDs

Expand Down Expand Up @@ -46,10 +49,6 @@ define( require => {
// cycles may pollute the data stream. See https://github.com/phetsims/axon/issues/179
reentrant: false,

// By default, check the options once in the constructor, not on each subsequent value validation, to improve
// performance in requirejs mode
validateOptionsOnValidateValue: false

// Property also supports validator options, see ValidatorDef.VALIDATOR_KEYS.

}, options );
Expand Down Expand Up @@ -136,7 +135,7 @@ define( require => {
}
ValidatorDef.validateValidator( validator );

this.validate = value => validate( value, validator );
this.validate = value => validate( value, validator, VALIDATE_OPTIONS_FALSE );

// validate the initial value
this.validate( value );
Expand Down
26 changes: 11 additions & 15 deletions js/ValidatorDef.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,6 @@ define( require => {
// {function(new: ObjectIO)} - A TypeIO used to specify the public typeing for PhET-iO. Each TypeIO must have a
// `validator` key specified that can be used for validation. See ObjectIO for an example.
'phetioType'

/**************************************
* Additionally, validation will always check the validator itself. However, for types like Property and Emitter,
* re-checking the validator every time the Property value changes or the Emitter emits wastes time. Hence cases like
* those can opt-out by specifying:
*
* validateOptionsOnValidateValue: false
*
* Note: this should not be a key in VALIDATOR_KEYS because the keys are reserved for checking the value itself,
* see implementation and usage of containsValidatorKey. Our "definition" of a validator is the makeup of the keys
* above, validateOptionsOnValidateValue is more of a meta-option that is not for checking the value itself, but
* whether to check the validator at the same time.
*********************/
];

const ValidatorDef = {
Expand Down Expand Up @@ -238,10 +225,19 @@ define( require => {
*/
isValueValid( value, validator, options ) {

options = options || ASSERTIONS_FALSE;
options = _.extend( {

// {boolean} - By default validation will always check the validity of the validator itself. However, for types like
// Property and Emitter re-checking the validator every time the Property value changes or the Emitter emits
// wastes cpu. Hence cases like those can opt-out
validateOptions: true,

// if true, throw an assertion "instead" of waiting to return a boolean
assertions: false
}, options );

// Use the same policy for whether to throw assertions when checking the validator itself.
if ( validator.validateOptionsOnValidateValue !== false && !axon.ValidatorDef.isValidValidator( validator, options ) ) {
if ( options.validateOptions !== false && !axon.ValidatorDef.isValidValidator( validator, options ) ) {
assert && options.assertions && assert( false, 'Invalid validator' );
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion js/ValidatorDefTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ define( require => {
assert.ok( ValidatorDef.isValueValid( [ [], [], [], [] ], { arrayElementType: [ Array ] } ), 'array array' );

window.assert && assert.throws( () => {
ValidatorDef.isValueValid( undefined, { arrayElementType: [ 'number', 'string' ], }, ASSERTIONS_TRUE );
ValidatorDef.isValueValid( undefined, { arrayElementType: [ 'number', 'string' ] }, ASSERTIONS_TRUE );
}, 'undefined is not a valid arrayElementType' );

window.assert && assert.throws( () => {
Expand Down
5 changes: 3 additions & 2 deletions js/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ define( require => {
* If assertions are enabled, assert out if the value does not adhere to the validator. No-op without assertions.
* @param {*} value
* @param {ValidatorDef} validator
* @param {Object} [options] - see ValidatorDef.isValueValid()
* @returns {*} - returns the input value for chaining
* @public
*/
const validate = ( value, validator ) => {
const validate = ( value, validator, options ) => {

if ( assert ) {

// Throws an error if not valid
ValidatorDef.isValueValid( value, validator, { assertions: true } );
ValidatorDef.isValueValid( value, validator, _.extend( { assertions: true }, options ) );
}
return value;
};
Expand Down

0 comments on commit f73877e

Please sign in to comment.