fix attr iteration

if we mutate hash while using it within `in-hash`, bad things happen
main
Matthew Butterick 2 years ago
parent 51d6c536d2
commit 71ad54fa78

@ -12,6 +12,9 @@
"param.rkt")
(provide (all-defined-out))
(module+ test
(require rackunit))
(define (for-each-attrs xs proc)
;; apply `proc` to each set of attrs in `xs`.
;; recursively descend from top to bottom.
@ -41,9 +44,15 @@
[other (raise-argument-error 'do-attr-iteration "key predicate" other)]))
(for-each-attrs qs
(λ (attrs parent-attrs)
(for ([(ak av) (in-hash attrs)]
;; we don't iterate with `in-hash` (or `in-hash-keys`) because
;; `attrs` might get mutated during the loop,
;; which invalidates the reference `in-hash` is using
(for* ([ak (in-list (hash-keys attrs))]
[av (in-value (hash-ref attrs ak))]
#:when (attr-predicate ak av))
(match (if wants-parent-attrs? (attr-proc ak av attrs parent-attrs) (attr-proc ak av attrs))
(match (if wants-parent-attrs?
(attr-proc ak av attrs parent-attrs)
(attr-proc ak av attrs))
;; void value: do nothing
[(? void?) (void)]
;; otherwise treat return value as new attr value
@ -62,8 +71,7 @@
[(attr-key? ak) av]
[(symbol? ak)
(match (hash-ref attr-lookup-table ak :unknown-key)
[(== :unknown-key eq?)
#:when strict-attrs?
[(== :unknown-key eq?) #:when strict-attrs?
(raise-argument-error 'upgrade-attr-keys "known attr" ak)]
[attr-key
(hash-remove! attrs ak)
@ -150,7 +158,6 @@
#:attr-proc (λ (ak av attrs) (parse-dimension av))))
(module+ test
(require rackunit)
(define-attr-list debug-attrs
[:foo (make-attr-cased-string-key 'foo)]
[:ps (make-attr-path-key 'ps)]

Loading…
Cancel
Save