fix(File): set Symbol.toStringTag to "File"

Closed
TA
3mo ago
+32-2

What does this PR do?

Fixes #14102.

new File(...) reported the wrong Symbol.toStringTag:

const file = new File(["Hello"], "file.txt");
file[Symbol.toStringTag];                       // before: "Blob"  → after: "File"
Object.prototype.toString.call(file);           // before: "[object Blob]" → after: "[object File]"

This diverges from Node and breaks fetch/form-data-style packages that branch on the tag (an instance is initially treated as a Blob).

Root cause

File and Blob share the same prototype object (File.prototype === Blob.prototype), so File instances inherit Blob's Symbol.toStringTag. Renaming it on the shared prototype is not an option (it would rename Blob too).

The fix

In src/jsc/bindings/JSDOMFile.cpp, give each File instance its own Symbol.toStringTag of "File" at construction time — the same approach JSS3File already uses. The property is defined non-enumerable and non-writable (matching the WebIDL Symbol.toStringTag descriptor: { configurable: true, enumerable: false, writable: false }) so it does not leak into object spreads. Blob is unaffected; instanceof File / instanceof Blob and file.name are unchanged.

Tests

Added test/regression/issue/14102.test.ts:

  • new File(...)[Symbol.toStringTag] === "File" and Object.prototype.toString.call(file) === "[object File]"
  • new Blob(...) still reports "Blob" / "[object Blob]"
  • instanceof File / instanceof Blob still true
  • the tag is non-enumerable and does not appear in { ...file }

Verified the test passes with the build and fails with USE_SYSTEM_BUN=1.