* Sets the property's input value. This is analogous to a CSS specified * value. Several values for the same property can be set on a node - one * per each setter. A repeated call for the same setter overwrites a * previously set input. This is similar to how the same CSS property can be
(prop, setter, value)
| 93 | * @template T |
| 94 | */ |
| 95 | set(prop, setter, value) { |
| 96 | devAssert(setter); |
| 97 | devAssert(value !== undefined); |
| 98 | |
| 99 | const {key} = prop; |
| 100 | |
| 101 | const inputsByKey = this.inputsByKey_ || (this.inputsByKey_ = new Map()); |
| 102 | let inputs = inputsByKey.get(key); |
| 103 | if (!inputs) { |
| 104 | inputs = { |
| 105 | values: [], |
| 106 | setters: [], |
| 107 | }; |
| 108 | inputsByKey.set(key, inputs); |
| 109 | } |
| 110 | const index = inputs.setters.indexOf(setter); |
| 111 | const changed = index == -1 || inputs.values[index] !== value; |
| 112 | if (index == -1) { |
| 113 | inputs.setters.push(setter); |
| 114 | inputs.values.push(value); |
| 115 | } else if (changed) { |
| 116 | inputs.values[index] = value; |
| 117 | } |
| 118 | |
| 119 | if (changed) { |
| 120 | // An input has been added to a node for a first time. This might |
| 121 | // affect all values in this and child nodes. The simplest algorithm |
| 122 | // here is to deep scan all descendants and refresh them. |
| 123 | // Optimization opportunity: in simple but common manipulations the |
| 124 | // deepscan can be avoided. |
| 125 | this.ping(prop, false); |
| 126 | if (isRecursive(prop)) { |
| 127 | deepScan( |
| 128 | this.contextNode_, |
| 129 | scan, |
| 130 | prop, |
| 131 | /*state=*/ true, |
| 132 | /*includeSelf=*/ false |
| 133 | ); |
| 134 | } |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | /** |
| 139 | * Unsets the input value for the specified property and setter. |
no test coverage detected