Skip to content

lib: add FileAPI support - #67277

Open
avivkeller wants to merge 3 commits into
nodejs:mainfrom
avivkeller:wpt-fileapi
Open

avivkeller wants to merge 3 commits into
nodejs:mainfrom
avivkeller:wpt-fileapi

Conversation

@avivkeller

@avivkeller avivkeller commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

Adds support for the following FileAPI interfaces:

  • FileReader
  • FileReaderSync
  • ProgressEvent

Signed-off-by: avivkeller <me@aviv.sh>
@avivkeller
avivkeller requested a review from panva November 5, 2026 15:47
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/startup
  • @nodejs/web-standards

@nodejs-github-bot nodejs-github-bot added lib / src Issues and PRs involving general changes in the lib/ or src/ directories. needs-ci PRs that need a full CI run. labels Nov 5, 2026
@codecov

codecov Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.00631% with 57 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.70%. Comparing base (3b209b2) to head (635dde8).
⚠️ Report is 20 commits behind head on main.

Files with missing lines Patch % Lines
lib/internal/filereader.js 92.66% 57 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #67277      +/-   ##
==========================================
+ Coverage   90.68%   90.70%   +0.01%     
==========================================
  Files         797      799       +2     
  Lines      279367   280464    +1097     
  Branches    53737    53874     +137     
==========================================
+ Hits       253344   254387    +1043     
- Misses      16319    16354      +35     
- Partials     9704     9723      +19     
Files with missing lines Coverage Δ
...internal/bootstrap/web/exposed-window-or-worker.js 94.20% <100.00%> (+0.30%) ⬆️
lib/internal/file.js 97.38% <100.00%> (+0.01%) ⬆️
lib/internal/progress_event.js 100.00% <100.00%> (ø)
lib/internal/webidl.js 100.00% <100.00%> (ø)
lib/internal/webworker.js 95.86% <100.00%> (+0.01%) ⬆️
lib/internal/filereader.js 92.66% <92.66%> (ø)

... and 42 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread lib/internal/filereader.js Resolved

@mcollina mcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Comment thread lib/internal/filereader.js Resolved
@mcollina mcollina added the semver-major PRs that contain breaking changes and should be released in the next major version. label Nov 5, 2026
Signed-off-by: avivkeller <me@aviv.sh>
KhafraDev

This comment was marked as resolved.

@avivkeller avivkeller added author ready PRs with CI started, the required approvals, and no outstanding review comments. commit-queue PRs queued for automated landing through the Commit Queue. request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. and removed commit-queue PRs queued for automated landing through the Commit Queue. labels Nov 5, 2026
Comment thread doc/api/globals.md Resolved
Comment thread doc/api/globals.md Resolved
Comment thread lib/internal/filereader.js Resolved
Comment thread lib/internal/filereader.js Resolved
Comment thread lib/internal/filereader.js Resolved
@github-actions github-actions Bot removed the request-ci Add this label to start a Jenkins CI on a PR. Only starts once the PR has an approving review. label Nov 5, 2026
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Comment thread lib/internal/filereader.js Resolved
Comment thread lib/internal/filereader.js Resolved

@jasnell jasnell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please mark initially as experimental.

@panva panva removed the author ready PRs with CI started, the required approvals, and no outstanding review comments. label Nov 5, 2026
Comment thread doc/api/globals.md Resolved
Comment thread doc/api/globals.md Outdated
A browser-compatible implementation of {FileReaderSync} from the [File API][].
It is exposed only inside a [Web Worker][] (`--experimental-web-worker`),
matching `[Exposed=(DedicatedWorker,SharedWorker)]`. It is not available on
the main thread or in threads created with `node:worker_threads`.

@jasnell jasnell Nov 5, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I question whether this restriction is actually necessary in Node.js. Specifically the "It is not available on the main thread" or in worker threads.

The restrictions that apply to the browser do not necessarily apply here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was marked resolved but it's still limited to web workers. The question is still open here.

Comment thread doc/api/globals.md Resolved
Comment thread test/parallel/test-filereader.js Resolved
Comment thread lib/internal/filereader.js Resolved
@jasnell

jasnell commented Nov 5, 2026

Copy link
Copy Markdown
Member

A separate AI-agent review flagged the following additional items:

  1. Progress events always report loaded = 0, total = 0, lengthComputable = false.
  • fireAProgressEvent() just does new ProgressEvent(name).
  • The File API spec's own example computes evt.loaded / evt.total. With this PR that gives NaN.
  • Chrome and Firefox fill in these values, and progress-bar code depends on them.
  • Fix: pass the bytes read so far and blob.size, as the XHR "fire a progress event" definition does.
  1. Events have isTrusted === false.
  • Other Node code marks events it fires itself as trusted with kTrustEvent (for example abort_controller.js and perf/performance.js).
  • Here that can't happen, because convertProgressEventInit drops the symbol before calling super().
  • Fix: let kTrustEvent pass through to Event, or set it after construction.
  1. The reader can get stuck in LOADING forever.
  • readOperation sets the state to 'loading' before it calls the public blob.stream(), getReader() and read() methods.
  • If a Blob subclass or patched prototype makes stream() throw, readyState stays at 1. Every later read then throws InvalidStateError (confirmed).
  • Fix: read through the blob's internal handle, as getBlobDataSync already does.
  • Related: it reads the public blob.type getter, so a subclass can change the data URL's MIME type (confirmed data:text/evil;...). Use the exported internal kType instead.
  1. loadend is fired in a separate task instead of the same one.
  • The spec fires loadend in the same task as load/error, right after it.
  • queueLoadEnd() schedules another setImmediate, so other code can run in between. I confirmed that a setImmediate scheduled inside onload runs before loadend.
  • The generation counter already handles a new read started from onload, so this can simply be inlined. The same applies to settleWithError.
  1. Data URLs for blobs with no type differ from browsers.
  • The PR follows the spec's literal wording and produces data:;base64,....
  • The WPT tests and browsers produce data:application/octet-stream;base64,.... The PR marks those two WPT tests as expected failures. (My note: this is one of the discrepancies between "browser-compatible" and "spec-compatible" that I noted in my review)
  • Choosing to break from both WPT and every browser deserves an explicit decision and probably an upstream spec issue. Otherwise, matching WPT seems better.
  1. "Replacement" encodings cause an error instead of decoding.
  • readAsText(blob, 'iso-2022-kr') (and similar labels) fires error with ERR_ENCODING_NOT_SUPPORTED.
  • The spec says to decode with the replacement decoder, which returns "\uFFFD" for non-empty input.
  • Builds without ICU will similarly fire error for any encoding other than UTF-8/UTF-16LE/latin1. I didn't test this, but it's probably worth documenting.
  1. FileList can't be created by users. createFileList is only used by tests, so the global exists just to satisfy interface-exposure checks. Is it actually worth shipping if it cannot be used?

@jasnell jasnell added the experimental Issues and PRs related to experimental features. label Nov 5, 2026
Signed-off-by: avivkeller <me@aviv.sh>
Comment thread doc/api/globals.md
added: REPLACEME
-->

> Stability: 1 - Experimental

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1.0 Active development?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

experimental Issues and PRs related to experimental features. lib / src Issues and PRs involving general changes in the lib/ or src/ directories. needs-ci PRs that need a full CI run. semver-major PRs that contain breaking changes and should be released in the next major version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants