Repository: denoland/deno
Pull request: fix(ext/node): use primordials in `ext/node/polyfills/internal/fs/handle.ts`

Towards #24236. This PR updates JS intrinsics with their primordial equivalents.

<!--
Before submitting a PR, please read https://docs.deno.com/runtime/manual/references/contributing

1. Give the PR a descriptive title.

  Examples of good title:
    - fix(std/http): Fix race condition in server
    - docs(console): Update docstrings
    - feat(doc): Handle nested reexports

  Examples of bad title:
    - fix #7123
    - update docs
    - fix bugs

2. Ensure there is a related issue and it is referenced in the PR text.
3. Ensure there are tests that cover the changes.
4. Ensure `cargo test` passes.
5. Ensure `./tools/format.js` passes without changing files.
6. Ensure `./tools/lint.js` passes.
7. Open as a draft PR if your work is still in progress. The CI won't run
   all steps, but you can add '[ci]' to a commit message to force it to.
8. If you would like to run the benchmarks on the CI, add the 'ci-bench' label.
-->


Changed files:
filename: ext/node/polyfills/internal/fs/handle.ts
patch: @@ -1,12 +1,9 @@
 // Copyright 2018-2025 the Deno authors. MIT license.
 
-// TODO(petamoriken): enable prefer-primordials for node polyfills
-// deno-lint-ignore-file prefer-primordials
-
 import { EventEmitter } from "node:events";
 import { Buffer } from "node:buffer";
 import { Mode, promises, read, ReadStream, write, WriteStream } from "node:fs";
-import { core } from "ext:core/mod.js";
+import { core, primordials } from "ext:core/mod.js";
 export type { BigIntStats, Stats } from "ext:deno_node/_fs/_fs_stat.ts";
 import {
   BinaryOptionsArgument,
@@ -23,6 +20,15 @@ import {
   CreateReadStreamOptions,
   CreateWriteStreamOptions,
 } from "node:fs/promises";
+const {
+  Error,
+  ObjectAssign,
+  ObjectPrototypeIsPrototypeOf,
+  Promise,
+  PromiseResolve,
+  SafeArrayIterator,
+  Uint8ArrayPrototype,
+} = primordials;
 
 interface WriteResult {
   bytesWritten: number;
@@ -62,7 +68,7 @@ export class FileHandle extends EventEmitter {
     length?: number,
     position?: number | null,
   ): Promise<ReadResult> {
-    if (bufferOrOpt instanceof Uint8Array) {
+    if (ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, bufferOrOpt)) {
       return new Promise((resolve, reject) => {
         read(
           this.fd,
@@ -109,7 +115,7 @@ export class FileHandle extends EventEmitter {
     lengthOrEncoding: number | string,
     position?: number,
   ): Promise<WriteResult> {
-    if (bufferOrStr instanceof Uint8Array) {
+    if (ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, bufferOrStr)) {
       const buffer = bufferOrStr;
       const offset = offsetOrPosition;
       const length = lengthOrEncoding;
@@ -151,7 +157,7 @@ export class FileHandle extends EventEmitter {
 
   close(): Promise<void> {
     // Note that Deno.close is not async
-    return Promise.resolve(core.close(this.fd));
+    return PromiseResolve(core.close(this.fd));
   }
 
   stat(): Promise<Stats>;
@@ -198,7 +204,7 @@ export class FileHandle extends EventEmitter {
 function assertNotClosed(handle: FileHandle, syscall: string) {
   if (handle.fd === -1) {
     const err = new Error("file closed");
-    throw Object.assign(err, {
+    throw ObjectAssign(err, {
       code: "EBADF",
       syscall,
     });
@@ -207,7 +213,7 @@ function assertNotClosed(handle: FileHandle, syscall: string) {
 
 function fsCall(fn, handle, ...args) {
   assertNotClosed(handle, fn.name);
-  return fn(handle.fd, ...args);
+  return fn(handle.fd, ...new SafeArrayIterator(args));
 }
 
 export default {