@@ -10,6 +10,7 @@ import {
10
10
dissoc ,
11
11
equals ,
12
12
evolve ,
13
+ findIndex ,
13
14
flatten ,
14
15
forEachObjIndexed ,
15
16
includes ,
@@ -396,12 +397,12 @@ function findInOutOverlap(outputs, inputs, head, dispatchError) {
396
397
}
397
398
398
399
function findMismatchedWildcards ( outputs , inputs , state , head , dispatchError ) {
399
- const { anyKeys : out0AnyKeys } = findWildcardKeys ( outputs [ 0 ] . id ) ;
400
- outputs . forEach ( ( out , outi ) => {
401
- if ( outi && ! equals ( findWildcardKeys ( out . id ) . anyKeys , out0AnyKeys ) ) {
400
+ const { matchKeys : out0MatchKeys } = findWildcardKeys ( outputs [ 0 ] . id ) ;
401
+ outputs . forEach ( ( out , i ) => {
402
+ if ( i && ! equals ( findWildcardKeys ( out . id ) . matchKeys , out0MatchKeys ) ) {
402
403
dispatchError ( 'Mismatched `MATCH` wildcards across `Output`s' , [
403
404
head ,
404
- `Output ${ outi } (${ combineIdAndProp ( out ) } )` ,
405
+ `Output ${ i } (${ combineIdAndProp ( out ) } )` ,
405
406
'does not have MATCH wildcards on the same keys as' ,
406
407
`Output 0 (${ combineIdAndProp ( outputs [ 0 ] ) } ).` ,
407
408
'MATCH wildcards must be on the same keys for all Outputs.' ,
@@ -414,9 +415,9 @@ function findMismatchedWildcards(outputs, inputs, state, head, dispatchError) {
414
415
[ state , 'State' ] ,
415
416
] . forEach ( ( [ args , cls ] ) => {
416
417
args . forEach ( ( arg , i ) => {
417
- const { anyKeys , allsmallerKeys} = findWildcardKeys ( arg . id ) ;
418
- const allWildcardKeys = anyKeys . concat ( allsmallerKeys ) ;
419
- const diff = difference ( allWildcardKeys , out0AnyKeys ) ;
418
+ const { matchKeys , allsmallerKeys} = findWildcardKeys ( arg . id ) ;
419
+ const allWildcardKeys = matchKeys . concat ( allsmallerKeys ) ;
420
+ const diff = difference ( allWildcardKeys , out0MatchKeys ) ;
420
421
if ( diff . length ) {
421
422
diff . sort ( ) ;
422
423
dispatchError ( '`Input` / `State` wildcards not in `Output`s' , [
@@ -639,7 +640,7 @@ export function computeGraphs(dependencies, dispatchError) {
639
640
* {[id]: {[prop]: [callback, ...]}}
640
641
* where callbacks are the matching specs from the original
641
642
* dependenciesRequest, but with outputs parsed to look like inputs,
642
- * and a list anyKeys added if the outputs have MATCH wildcards.
643
+ * and a list matchKeys added if the outputs have MATCH wildcards.
643
644
* For outputMap there should only ever be one callback per id/prop
644
645
* but for inputMap there may be many.
645
646
*
@@ -785,9 +786,10 @@ export function computeGraphs(dependencies, dispatchError) {
785
786
// Also collect MATCH keys in the output (all outputs must share these)
786
787
// and ALL keys in the first output (need not be shared but we'll use
787
788
// the first output for calculations) for later convenience.
788
- const { anyKeys, hasALL} = findWildcardKeys ( outputs [ 0 ] . id ) ;
789
+ const { matchKeys} = findWildcardKeys ( outputs [ 0 ] . id ) ;
790
+ const firstSingleOutput = findIndex ( o => ! isMultiValued ( o . id ) , outputs ) ;
789
791
const finalDependency = mergeRight (
790
- { hasALL , anyKeys , outputs} ,
792
+ { matchKeys , firstSingleOutput , outputs} ,
791
793
dependency
792
794
) ;
793
795
@@ -820,23 +822,20 @@ export function computeGraphs(dependencies, dispatchError) {
820
822
}
821
823
822
824
function findWildcardKeys ( id ) {
823
- const anyKeys = [ ] ;
825
+ const matchKeys = [ ] ;
824
826
const allsmallerKeys = [ ] ;
825
- let hasALL = false ;
826
827
if ( typeof id === 'object' ) {
827
828
forEachObjIndexed ( ( val , key ) => {
828
829
if ( val === MATCH ) {
829
- anyKeys . push ( key ) ;
830
+ matchKeys . push ( key ) ;
830
831
} else if ( val === ALLSMALLER ) {
831
832
allsmallerKeys . push ( key ) ;
832
- } else if ( val === ALL ) {
833
- hasALL = true ;
834
833
}
835
834
} , id ) ;
836
- anyKeys . sort ( ) ;
835
+ matchKeys . sort ( ) ;
837
836
allsmallerKeys . sort ( ) ;
838
837
}
839
- return { anyKeys , allsmallerKeys, hasALL } ;
838
+ return { matchKeys , allsmallerKeys} ;
840
839
}
841
840
842
841
/*
@@ -1048,31 +1047,6 @@ function getCallbackByOutput(graphs, paths, id, prop) {
1048
1047
return makeResolvedCallback ( callback , resolve , anyVals ) ;
1049
1048
}
1050
1049
1051
- /*
1052
- * If there are ALL keys we need to reduce a set of outputs resolved
1053
- * from an input to one item per combination of MATCH values.
1054
- * That will give one result per callback invocation.
1055
- */
1056
- function reduceALLOuts ( outs , anyKeys , hasALL ) {
1057
- if ( ! hasALL ) {
1058
- return outs ;
1059
- }
1060
- if ( ! anyKeys . length ) {
1061
- // If there's ALL but no MATCH, there's only one invocation
1062
- // of the callback, so just base it off the first output.
1063
- return [ outs [ 0 ] ] ;
1064
- }
1065
- const anySeen = { } ;
1066
- return outs . filter ( i => {
1067
- const matchKeys = JSON . stringify ( props ( anyKeys , i . id ) ) ;
1068
- if ( ! anySeen [ matchKeys ] ) {
1069
- anySeen [ matchKeys ] = 1 ;
1070
- return true ;
1071
- }
1072
- return false ;
1073
- } ) ;
1074
- }
1075
-
1076
1050
function addResolvedFromOutputs ( callback , outPattern , outs , matches ) {
1077
1051
const out0Keys = Object . keys ( outPattern . id ) . sort ( ) ;
1078
1052
const out0PatternVals = props ( out0Keys , outPattern . id ) ;
@@ -1088,6 +1062,51 @@ function addResolvedFromOutputs(callback, outPattern, outs, matches) {
1088
1062
} ) ;
1089
1063
}
1090
1064
1065
+ function addAllResolvedFromOutputs ( resolve , paths , matches ) {
1066
+ return callback => {
1067
+ const { matchKeys, firstSingleOutput, outputs} = callback ;
1068
+ if ( matchKeys . length ) {
1069
+ const singleOutPattern = outputs [ firstSingleOutput ] ;
1070
+ if ( singleOutPattern ) {
1071
+ addResolvedFromOutputs (
1072
+ callback ,
1073
+ singleOutPattern ,
1074
+ resolve ( paths ) ( singleOutPattern ) ,
1075
+ matches
1076
+ ) ;
1077
+ } else {
1078
+ /*
1079
+ * If every output has ALL we need to reduce resolved set
1080
+ * to one item per combination of MATCH values.
1081
+ * That will give one result per callback invocation.
1082
+ */
1083
+ const anySeen = { } ;
1084
+ outputs . forEach ( outPattern => {
1085
+ const outSet = resolve ( paths ) ( outPattern ) . filter ( i => {
1086
+ const matchStr = JSON . stringify ( props ( matchKeys , i . id ) ) ;
1087
+ if ( ! anySeen [ matchStr ] ) {
1088
+ anySeen [ matchStr ] = 1 ;
1089
+ return true ;
1090
+ }
1091
+ return false ;
1092
+ } ) ;
1093
+ addResolvedFromOutputs (
1094
+ callback ,
1095
+ outPattern ,
1096
+ outSet ,
1097
+ matches
1098
+ ) ;
1099
+ } ) ;
1100
+ }
1101
+ } else {
1102
+ const cb = makeResolvedCallback ( callback , resolve , '' ) ;
1103
+ if ( flatten ( cb . getOutputs ( paths ) ) . length ) {
1104
+ matches . push ( cb ) ;
1105
+ }
1106
+ }
1107
+ } ;
1108
+ }
1109
+
1091
1110
/*
1092
1111
* For a given id and prop find all callbacks it's an input of.
1093
1112
*
@@ -1111,21 +1130,9 @@ export function getCallbacksByInput(graphs, paths, id, prop, changeType) {
1111
1130
return [ ] ;
1112
1131
}
1113
1132
1114
- const baseResolve = resolveDeps ( ) ;
1115
- callbacks . forEach ( callback => {
1116
- const { anyKeys, hasALL} = callback ;
1117
- if ( anyKeys ) {
1118
- const out0Pattern = callback . outputs [ 0 ] ;
1119
- const out0Set = reduceALLOuts (
1120
- baseResolve ( paths ) ( out0Pattern ) ,
1121
- anyKeys ,
1122
- hasALL
1123
- ) ;
1124
- addResolvedFromOutputs ( callback , out0Pattern , out0Set , matches ) ;
1125
- } else {
1126
- matches . push ( makeResolvedCallback ( callback , baseResolve , '' ) ) ;
1127
- }
1128
- } ) ;
1133
+ callbacks . forEach (
1134
+ addAllResolvedFromOutputs ( resolveDeps ( ) , paths , matches )
1135
+ ) ;
1129
1136
} else {
1130
1137
// wildcard version
1131
1138
const keys = Object . keys ( id ) . sort ( ) ;
@@ -1137,23 +1144,13 @@ export function getCallbacksByInput(graphs, paths, id, prop, changeType) {
1137
1144
}
1138
1145
patterns . forEach ( pattern => {
1139
1146
if ( idMatch ( keys , vals , pattern . values ) ) {
1140
- const resolve = resolveDeps ( keys , vals , pattern . values ) ;
1141
- pattern . callbacks . forEach ( callback => {
1142
- const out0Pattern = callback . outputs [ 0 ] ;
1143
- const { anyKeys, hasALL} = callback ;
1144
- const out0Set = reduceALLOuts (
1145
- resolve ( paths ) ( out0Pattern ) ,
1146
- anyKeys ,
1147
- hasALL
1148
- ) ;
1149
-
1150
- addResolvedFromOutputs (
1151
- callback ,
1152
- out0Pattern ,
1153
- out0Set ,
1147
+ pattern . callbacks . forEach (
1148
+ addAllResolvedFromOutputs (
1149
+ resolveDeps ( keys , vals , pattern . values ) ,
1150
+ paths ,
1154
1151
matches
1155
- ) ;
1156
- } ) ;
1152
+ )
1153
+ ) ;
1157
1154
}
1158
1155
} ) ;
1159
1156
}
0 commit comments