Repository: denoland/deno
Pull request: fix(ext/node): add type check to LibuvStreamWrap.writeBuffer

This PR adds a type check of the input to LibuvStreamWrap.prototype.writeBuffer method, and enables `parallel/test-stream-base-typechecking.js` case.

towards #29802 

Changed files:
filename: ext/node/polyfills/internal_binding/stream_wrap.ts
patch: @@ -37,6 +37,7 @@ const {
   Symbol,
   TypedArrayPrototypeSlice,
   Uint8Array,
+  Uint8ArrayPrototype,
 } = primordials;
 import { op_can_write_vectored, op_raw_write_vectored } from "ext:core/ops";
 
@@ -51,6 +52,7 @@ import {
 } from "ext:deno_node/internal_binding/async_wrap.ts";
 import { codeMap } from "ext:deno_node/internal_binding/uv.ts";
 import { _readWithCancelHandle } from "ext:deno_io/12_io.js";
+import { NodeTypeError } from "ext:deno_node/internal/errors.ts";
 
 export interface Reader {
   read(p: Uint8Array): Promise<number | null>;
@@ -200,6 +202,13 @@ export class LibuvStreamWrap extends HandleWrap {
    * @return An error status code.
    */
   writeBuffer(req: WriteWrap<LibuvStreamWrap>, data: Uint8Array): number {
+    if (!ObjectPrototypeIsPrototypeOf(Uint8ArrayPrototype, data)) {
+      throw new NodeTypeError(
+        "ERR_INVALID_ARG_TYPE",
+        "Second argument must be a buffer",
+      );
+    }
+
     this.#write(req, data);
 
     return 0;

filename: tests/node_compat/config.jsonc
patch: @@ -1031,6 +1031,7 @@
       "test-stream-await-drain-writers-in-synchronously-recursion-write.js",
       "test-stream-backpressure.js",
       "test-stream-base-prototype-accessors-enumerability.js",
+      "test-stream-base-typechecking.js",
       "test-stream-big-packet.js",
       "test-stream-big-push.js",
       "test-stream-catch-rejections.js",

filename: tests/node_compat/runner/TODO.md
patch: @@ -1,7 +1,7 @@
 <!-- deno-fmt-ignore-file -->
 # Remaining Node Tests
 
-1216 tests out of 3993 have been ported from Node 23.9.0 (30.45% ported, 70.17% remaining).
+1219 tests out of 3993 have been ported from Node 23.9.0 (30.53% ported, 70.10% remaining).
 
 NOTE: This file should not be manually edited. Please edit `tests/node_compat/config.json` and run `deno task setup` in `tests/node_compat/runner` dir instead.
 
@@ -2036,7 +2036,6 @@ NOTE: This file should not be manually edited. Please edit `tests/node_compat/co
 - [parallel/test-stdout-close-unref.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-stdout-close-unref.js)
 - [parallel/test-stdout-to-file.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-stdout-to-file.js)
 - [parallel/test-strace-openat-openssl.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-strace-openat-openssl.js)
-- [parallel/test-stream-base-typechecking.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-stream-base-typechecking.js)
 - [parallel/test-stream-destroy.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-stream-destroy.js)
 - [parallel/test-stream-pipe-deadlock.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-stream-pipe-deadlock.js)
 - [parallel/test-stream-pipeline-http2.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-stream-pipeline-http2.js)

filename: tests/node_compat/test/parallel/test-stream-base-typechecking.js
patch: @@ -0,0 +1,25 @@
+// deno-fmt-ignore-file
+// deno-lint-ignore-file
+
+// Copyright Joyent and Node contributors. All rights reserved. MIT license.
+// Taken from Node 23.9.0
+// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually.
+
+'use strict';
+const common = require('../common');
+const assert = require('assert');
+const net = require('net');
+
+const server = net.createServer().listen(0, common.mustCall(() => {
+  const client = net.connect(server.address().port, common.mustCall(() => {
+    assert.throws(() => {
+      client.write('broken', 'buffer');
+    }, {
+      name: 'TypeError',
+      code: 'ERR_INVALID_ARG_TYPE',
+      message: 'Second argument must be a buffer'
+    });
+    client.destroy();
+    server.close();
+  }));
+}));