(state_, dispatchError)
| 505 | } |
| 506 | |
| 507 | export function validateCallbacksToLayout(state_, dispatchError) { |
| 508 | const {config, graphs, layout: layout_, paths: paths_} = state_; |
| 509 | const validateIds = !config.suppress_callback_exceptions; |
| 510 | let layout, paths; |
| 511 | if (validateIds && config.validation_layout) { |
| 512 | layout = config.validation_layout; |
| 513 | paths = computePaths(layout, [], null, paths_.events); |
| 514 | } else { |
| 515 | layout = layout_; |
| 516 | paths = paths_; |
| 517 | } |
| 518 | const {outputMap, inputMap, outputPatterns, inputPatterns} = graphs; |
| 519 | |
| 520 | function tail(callbacks) { |
| 521 | return ( |
| 522 | 'This ID was used in the callback(s) for Output(s):\n ' + |
| 523 | callbacks |
| 524 | .map(({outputs}) => outputs.map(combineIdAndProp).join(', ')) |
| 525 | .join('\n ') |
| 526 | ); |
| 527 | } |
| 528 | |
| 529 | function missingId(id, cls, callbacks) { |
| 530 | dispatchError('ID not found in layout', [ |
| 531 | `Attempting to connect a callback ${cls} item to component:`, |
| 532 | ` "${stringifyId(id)}"`, |
| 533 | 'but no components with that id exist in the layout.', |
| 534 | '', |
| 535 | 'If you are assigning callbacks to components that are', |
| 536 | 'generated by other callbacks (and therefore not in the', |
| 537 | 'initial layout), you can suppress this exception by setting', |
| 538 | '`suppress_callback_exceptions=True`.', |
| 539 | tail(callbacks) |
| 540 | ]); |
| 541 | } |
| 542 | |
| 543 | function validateProp(id, idPath, rawProp, cls, callbacks) { |
| 544 | const prop = rawProp.split('@')[0]; |
| 545 | const component = path(idPath, layout); |
| 546 | const element = Registry.resolve(component); |
| 547 | |
| 548 | // note: Flow components do not have propTypes, so we can't validate. |
| 549 | if (element && element.propTypes && !element.propTypes[prop]) { |
| 550 | // look for wildcard props (ie data-* etc) |
| 551 | for (const propName in element.propTypes) { |
| 552 | const last = propName.length - 1; |
| 553 | if ( |
| 554 | propName.charAt(last) === '*' && |
| 555 | prop.substr(0, last) === propName.substr(0, last) |
| 556 | ) { |
| 557 | return; |
| 558 | } |
| 559 | } |
| 560 | const {type, namespace} = component; |
| 561 | dispatchError('Invalid prop for this component', [ |
| 562 | `Property "${prop}" was used with component ID:`, |
| 563 | ` ${JSON.stringify(id)}`, |
| 564 | `in one of the ${cls} items of a callback.`, |
no test coverage detected
searching dependent graphs…