         }
     }
 
+    private func clearCachedValues() {
+        for fn in _valueClearers { fn() }
+    }
+
     private func cleanUp() {
         assert(_setupComplete)
         if let error = _unhandledError, error.isTransient {

        _evaluating.removeAll()
        _getters.removeAll()
        _cachedExpressions.removeAll()
        for child in children {
            child.cleanUp()
        }

        return view.isHidden
    }

    // TODO: should this be public?
    public var frame: CGRect {
        return attempt {
            CGRect(
                x: try CGFloat(doubleValue(forSymbol: "left")),
                y: try CGFloat(doubleValue(forSymbol: "top")),
                width: try CGFloat(doubleValue(forSymbol: "width")),
                height: try CGFloat(doubleValue(forSymbol: "height"))
            )
        } ?? .zero
    }

    private func inferContentSize() throws -> CGSize {
