Skip to content

fix(core): return raw host objects (File/Blob) from form.data#2

Open
LouisHaftmann wants to merge 2 commits into
masterfrom
fix/form-data-raw-host-objects
Open

fix(core): return raw host objects (File/Blob) from form.data#2
LouisHaftmann wants to merge 2 commits into
masterfrom
fix/form-data-raw-host-objects

Conversation

@LouisHaftmann

Copy link
Copy Markdown
Contributor

Problem

form.data is wrapped by on-change for dirty tracking. on-change lazily proxies every nested object on read and treats File/Blob as plain objects — so form.data.files[0] returned a Proxy wrapping the File. Native accessors (.name / .size / .type / .arrayBuffer()) are bound to internal slots and throw TypeError: Illegal invocation when the receiver is the proxy instead of the real object. toRaw doesn't unwrap it (it's an on-change proxy, not a Vue reactive), and field.value only worked by accident.

Vue's reactive already leaves host objects raw (getTargetTypeINVALID), so on-change was the sole culprit.

Fix

on-change 6.0.2 (latest) has no leaf/allow-list hook, so this adds a pnpm patch to its prepareValue: any non-plain object that isn't a tracked builtin (Array / Date / Map / Set / typed array) is returned by reference and never wrapped. This fixes form.data, field.value, and field.model at once (all read through the proxy), preserves object identity — so dirty tracking still fires on identity change with no blob deep-diff — and confirms klona/full clones File by reference.

Tests

  • core: form.data.<path> returns raw File/Blob with working native getters; field.value identity stays raw after an unrelated change + re-validation; File in sourceValues survives clone + reset(); dirty tracking fires on file change.
  • vue: field.model returns the raw File.

Notes

  • Typed arrays remain proxied (they're isBuiltinWithMutableMethods, which on-change intentionally tracks). Acceptance only required File/Blob.
  • Two failures on this branch (core > field > readonly, entire react suite) are pre-existing on master and unrelated: Vue warn dedup, and react-test-renderer.act removed in React 19.

🤖 Generated with Claude Code

on-change lazily proxies nested objects on read and treated host
objects like File/Blob as plain objects, so form.data.<path> returned
a Proxy wrapping the File. Native accessors (name, size, type,
arrayBuffer) are bound to internal slots and throw "Illegal invocation"
when the receiver is the Proxy instead of the real object.

Patch on-change's prepareValue to treat any non-plain object that isn't
a tracked builtin (Array/Date/Map/Set/typed array) as an opaque leaf,
returning it by reference and never wrapping it. This fixes form.data,
field.value and field.model, which all read through the proxy.
@LouisHaftmann
LouisHaftmann force-pushed the fix/form-data-raw-host-objects branch from 1888d56 to 51506d7 Compare July 21, 2026 10:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants