@@ -10,6 +10,8 @@ import InvalidControlInput from './errors/InvalidControlInput.js'
10
10
import legacyMethods from './legacy.js'
11
11
import { precoerceNumber } from './utilities/downgrade.js'
12
12
13
+ const INVALID_ARGUMENTS = { type : 'Invalid Arguments' }
14
+
13
15
function isDeterministic ( method , engine , buildState ) {
14
16
if ( Array . isArray ( method ) ) {
15
17
return method . every ( ( i ) => isDeterministic ( i , engine , buildState ) )
@@ -69,6 +71,8 @@ const defaultMethods = {
69
71
return res
70
72
} ,
71
73
'*' : ( data ) => {
74
+ // eslint-disable-next-line no-throw-literal
75
+ if ( data . length === 0 ) throw INVALID_ARGUMENTS
72
76
let res = 1
73
77
for ( let i = 0 ; i < data . length ; i ++ ) {
74
78
if ( data [ i ] && typeof data [ i ] === 'object' ) throw NaN
@@ -79,12 +83,18 @@ const defaultMethods = {
79
83
} ,
80
84
'/' : ( data ) => {
81
85
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
+ }
82
92
let res = + data [ 0 ]
83
93
for ( let i = 1 ; i < data . length ; i ++ ) {
84
94
if ( ( data [ i ] && typeof data [ i ] === 'object' ) || ! data [ i ] ) throw NaN
85
95
res /= + data [ i ]
86
96
}
87
- if ( Number . isNaN ( res ) ) throw NaN
97
+ if ( Number . isNaN ( res ) || res === Infinity ) throw NaN
88
98
return res
89
99
} ,
90
100
'-' : ( data ) => {
@@ -94,6 +104,7 @@ const defaultMethods = {
94
104
if ( typeof data === 'boolean' ) return precoerceNumber ( - data )
95
105
if ( typeof data === 'object' && ! Array . isArray ( data ) ) throw NaN
96
106
if ( data [ 0 ] && typeof data [ 0 ] === 'object' ) throw NaN
107
+ if ( data . length === 0 ) return 0
97
108
if ( data . length === 1 ) return - data [ 0 ]
98
109
let res = data [ 0 ]
99
110
for ( let i = 1 ; i < data . length ; i ++ ) {
@@ -105,6 +116,8 @@ const defaultMethods = {
105
116
} ,
106
117
'%' : ( data ) => {
107
118
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
108
121
let res = + data [ 0 ]
109
122
for ( let i = 1 ; i < data . length ; i ++ ) {
110
123
if ( data [ i ] && typeof data [ i ] === 'object' ) throw NaN
@@ -980,15 +993,21 @@ function numberCoercion (i, buildState) {
980
993
981
994
// @ts -ignore Allow custom attribute
982
995
defaultMethods [ '+' ] . 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
+ }
984
1000
if ( typeof data === 'string' || typeof data === 'number' || typeof data === 'boolean' ) return `precoerceNumber(+${ buildString ( data , buildState ) } )`
985
1001
return buildState . compile `(Array.isArray(prev = ${ data } ) ? prev.reduce((a,b) => (+a)+(+precoerceNumber(b)), 0) : +precoerceNumber(prev))`
986
1002
}
987
1003
988
1004
// @ts -ignore Allow custom attribute
989
1005
defaultMethods [ '%' ] . 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)))`
992
1011
}
993
1012
994
1013
// @ts -ignore Allow custom attribute
@@ -999,26 +1018,35 @@ defaultMethods.in.compile = function (data, buildState) {
999
1018
1000
1019
// @ts -ignore Allow custom attribute
1001
1020
defaultMethods [ '-' ] . 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
+ }
1003
1025
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))`
1005
1027
}
1006
1028
// @ts -ignore Allow custom attribute
1007
1029
defaultMethods [ '/' ] . compile = function ( data , buildState ) {
1008
1030
if ( Array . isArray ( data ) ) {
1031
+ if ( data . length === 0 ) throw INVALID_ARGUMENTS
1032
+ if ( data . length === 1 ) data = [ 1 , data [ 0 ] ]
1009
1033
return `precoerceNumber(${ data . map ( ( i , x ) => {
1010
1034
let res = numberCoercion ( i , buildState )
1011
1035
if ( x && res === '+0' ) precoerceNumber ( NaN )
1012
1036
if ( x ) res = `precoerceNumber(${ res } || NaN)`
1013
1037
return res
1014
1038
} ) . join ( ' / ' ) } )`
1015
1039
}
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)))`
1017
1041
}
1018
1042
// @ts -ignore Allow custom attribute
1019
1043
defaultMethods [ '*' ] . 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)))`
1022
1050
}
1023
1051
1024
1052
// @ts -ignore Allow custom attribute
0 commit comments