@@ -10,6 +10,8 @@ import InvalidControlInput from './errors/InvalidControlInput.js'
1010import legacyMethods from './legacy.js'
1111import { precoerceNumber } from './utilities/downgrade.js'
1212
13+ const INVALID_ARGUMENTS = { type : 'Invalid Arguments' }
14+
1315function isDeterministic ( method , engine , buildState ) {
1416 if ( Array . isArray ( method ) ) {
1517 return method . every ( ( i ) => isDeterministic ( i , engine , buildState ) )
@@ -69,6 +71,8 @@ const defaultMethods = {
6971 return res
7072 } ,
7173 '*' : ( data ) => {
74+ // eslint-disable-next-line no-throw-literal
75+ if ( data . length === 0 ) throw INVALID_ARGUMENTS
7276 let res = 1
7377 for ( let i = 0 ; i < data . length ; i ++ ) {
7478 if ( data [ i ] && typeof data [ i ] === 'object' ) throw NaN
@@ -79,12 +83,18 @@ const defaultMethods = {
7983 } ,
8084 '/' : ( data ) => {
8185 if ( data [ 0 ] && typeof data [ 0 ] === 'object' ) throw NaN
86+ // eslint-disable-next-line no-throw-literal
87+ if ( data . length === 0 ) throw INVALID_ARGUMENTS
88+ if ( data . length === 1 ) {
89+ if ( ! + data [ 0 ] || ( data [ 0 ] && typeof data [ 0 ] === 'object' ) ) throw NaN
90+ return 1 / + data [ 0 ]
91+ }
8292 let res = + data [ 0 ]
8393 for ( let i = 1 ; i < data . length ; i ++ ) {
8494 if ( ( data [ i ] && typeof data [ i ] === 'object' ) || ! data [ i ] ) throw NaN
8595 res /= + data [ i ]
8696 }
87- if ( Number . isNaN ( res ) ) throw NaN
97+ if ( Number . isNaN ( res ) || res === Infinity ) throw NaN
8898 return res
8999 } ,
90100 '-' : ( data ) => {
@@ -94,6 +104,7 @@ const defaultMethods = {
94104 if ( typeof data === 'boolean' ) return precoerceNumber ( - data )
95105 if ( typeof data === 'object' && ! Array . isArray ( data ) ) throw NaN
96106 if ( data [ 0 ] && typeof data [ 0 ] === 'object' ) throw NaN
107+ if ( data . length === 0 ) return 0
97108 if ( data . length === 1 ) return - data [ 0 ]
98109 let res = data [ 0 ]
99110 for ( let i = 1 ; i < data . length ; i ++ ) {
@@ -105,6 +116,8 @@ const defaultMethods = {
105116 } ,
106117 '%' : ( data ) => {
107118 if ( data [ 0 ] && typeof data [ 0 ] === 'object' ) throw NaN
119+ // eslint-disable-next-line no-throw-literal
120+ if ( data . length < 2 ) throw INVALID_ARGUMENTS
108121 let res = + data [ 0 ]
109122 for ( let i = 1 ; i < data . length ; i ++ ) {
110123 if ( data [ i ] && typeof data [ i ] === 'object' ) throw NaN
@@ -980,15 +993,21 @@ function numberCoercion (i, buildState) {
980993
981994// @ts -ignore Allow custom attribute
982995defaultMethods [ '+' ] . compile = function ( data , buildState ) {
983- if ( Array . isArray ( data ) ) return `precoerceNumber(${ data . map ( i => numberCoercion ( i , buildState ) ) . join ( ' + ' ) } )`
996+ if ( Array . isArray ( data ) ) {
997+ if ( data . length === 0 ) return '(+0)'
998+ return `precoerceNumber(${ data . map ( i => numberCoercion ( i , buildState ) ) . join ( ' + ' ) } )`
999+ }
9841000 if ( typeof data === 'string' || typeof data === 'number' || typeof data === 'boolean' ) return `precoerceNumber(+${ buildString ( data , buildState ) } )`
9851001 return buildState . compile `(Array.isArray(prev = ${ data } ) ? prev.reduce((a,b) => (+a)+(+precoerceNumber(b)), 0) : +precoerceNumber(prev))`
9861002}
9871003
9881004// @ts -ignore Allow custom attribute
9891005defaultMethods [ '%' ] . compile = function ( data , buildState ) {
990- if ( Array . isArray ( data ) ) return `precoerceNumber(${ data . map ( i => numberCoercion ( i , buildState ) ) . join ( ' % ' ) } )`
991- return `(${ buildString ( data , buildState ) } ).reduce((a,b) => (+precoerceNumber(a))%(+precoerceNumber(b)))`
1006+ if ( Array . isArray ( data ) ) {
1007+ if ( data . length < 2 ) throw INVALID_ARGUMENTS
1008+ return `precoerceNumber(${ data . map ( i => numberCoercion ( i , buildState ) ) . join ( ' % ' ) } )`
1009+ }
1010+ return `assertSize(${ buildString ( data , buildState ) } , 2).reduce((a,b) => (+precoerceNumber(a))%(+precoerceNumber(b)))`
9921011}
9931012
9941013// @ts -ignore Allow custom attribute
@@ -999,26 +1018,35 @@ defaultMethods.in.compile = function (data, buildState) {
9991018
10001019// @ts -ignore Allow custom attribute
10011020defaultMethods [ '-' ] . compile = function ( data , buildState ) {
1002- if ( Array . isArray ( data ) ) return `${ data . length === 1 ? '-' : '' } precoerceNumber(${ data . map ( i => numberCoercion ( i , buildState ) ) . join ( ' - ' ) } )`
1021+ if ( Array . isArray ( data ) ) {
1022+ if ( data . length === 0 ) return '(-0)'
1023+ return `${ data . length === 1 ? '-' : '' } precoerceNumber(${ data . map ( i => numberCoercion ( i , buildState ) ) . join ( ' - ' ) } )`
1024+ }
10031025 if ( typeof data === 'string' || typeof data === 'number' ) return `(-${ buildString ( data , buildState ) } )`
1004- return buildState . compile `(Array.isArray(prev = ${ data } ) ? prev.length === 1 ? -precoerceNumber(prev[0]) : prev.reduce((a,b) => (+precoerceNumber(a))-(+precoerceNumber(b))) : -precoerceNumber(prev))`
1026+ return buildState . compile `(Array.isArray(prev = ${ data } ) ? prev.length === 0 ? 0 : prev.length === 1 ? -precoerceNumber(prev[0]) : prev.reduce((a,b) => (+precoerceNumber(a))-(+precoerceNumber(b))) : -precoerceNumber(prev))`
10051027}
10061028// @ts -ignore Allow custom attribute
10071029defaultMethods [ '/' ] . compile = function ( data , buildState ) {
10081030 if ( Array . isArray ( data ) ) {
1031+ if ( data . length === 0 ) throw INVALID_ARGUMENTS
1032+ if ( data . length === 1 ) data = [ 1 , data [ 0 ] ]
10091033 return `precoerceNumber(${ data . map ( ( i , x ) => {
10101034 let res = numberCoercion ( i , buildState )
10111035 if ( x && res === '+0' ) precoerceNumber ( NaN )
10121036 if ( x ) res = `precoerceNumber(${ res } || NaN)`
10131037 return res
10141038 } ) . join ( ' / ' ) } )`
10151039 }
1016- return `( ${ buildString ( data , buildState ) } ) .reduce((a,b) => (+precoerceNumber(a))/(+precoerceNumber(b || NaN)))`
1040+ return `assertSize(prev = ${ buildString ( data , buildState ) } , 1) && prev.length === 1 ? 1 / precoerceNumber(prev[0] || NaN) : prev .reduce((a,b) => (+precoerceNumber(a))/(+precoerceNumber(b || NaN)))`
10171041}
10181042// @ts -ignore Allow custom attribute
10191043defaultMethods [ '*' ] . compile = function ( data , buildState ) {
1020- if ( Array . isArray ( data ) ) return `precoerceNumber(${ data . map ( i => numberCoercion ( i , buildState ) ) . join ( ' * ' ) } )`
1021- return `(${ buildString ( data , buildState ) } ).reduce((a,b) => (+precoerceNumber(a))*(+precoerceNumber(b)))`
1044+ if ( Array . isArray ( data ) ) {
1045+ // eslint-disable-next-line no-throw-literal
1046+ if ( data . length === 0 ) throw INVALID_ARGUMENTS
1047+ return `precoerceNumber(${ data . map ( i => numberCoercion ( i , buildState ) ) . join ( ' * ' ) } )`
1048+ }
1049+ return `assertSize(${ buildString ( data , buildState ) } , 1).reduce((a,b) => (+precoerceNumber(a))*(+precoerceNumber(b)))`
10221050}
10231051
10241052// @ts -ignore Allow custom attribute
0 commit comments