From 07158d73706fb0096cb6b08ec915b625e51f7ecf Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa <stibium121@gmail.com> Date: Thu, 29 Apr 2021 17:56:54 +0900 Subject: [PATCH 1/4] feat(std/node): add writeBuffer of internal binding fs module --- node/internal_binding/README.md | 8 ++++ node/internal_binding/fs.ts | 74 ++++++++++++++++++++++++++++++++ node/internal_binding/fs_test.ts | 52 ++++++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 node/internal_binding/README.md create mode 100644 node/internal_binding/fs.ts create mode 100644 node/internal_binding/fs_test.ts diff --git a/node/internal_binding/README.md b/node/internal_binding/README.md new file mode 100644 index 000000000000..11692d1eba87 --- /dev/null +++ b/node/internal_binding/README.md @@ -0,0 +1,8 @@ +The modules in this directory implement (simulate) C++ bindings inplemented in +src/ directory of Node.js + +These bindings are created in the node.js source code by using +`NODE_MODULE_CONTEXT_AWARE_INTERNAL`. + +See: +https://github.com/nodejs/node/blob/e46c680bf2b211bbd52cf959ca17ee98c7f657f5/src/README.md diff --git a/node/internal_binding/fs.ts b/node/internal_binding/fs.ts new file mode 100644 index 000000000000..0aae7c98d4d5 --- /dev/null +++ b/node/internal_binding/fs.ts @@ -0,0 +1,74 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +import { assert } from "../../testing/asserts.ts"; +// This module implements functions in https://github.com/nodejs/node/blob/master/src/node_file.cc + +/** + * Write to the given file from the given buffer asynchronously. + * + * Implements async part of WriteBuffer in src/node_file.cc + * See: https://github.com/nodejs/node/blob/e9ed113/src/node_file.cc#L1818 + * + * @param fs file descriptor + * @param buffer the data to write + * @param offset where in the buffer to start from + * @param length how much to write + * @param position if integer, position to write at in the file. if null, write from the current position + * @param callback callback function + */ +export function writeBuffer( + fd: number, + buffer: Uint8Array, + offset: number, + length: number, + position: number | null, + callback?: (err: Error, n: number) => void, +): void { + throw new Error("unimplemented!"); +} + +/** + * Write to the given file from the given buffer synchronously. + * + * Implements sync part of WriteBuffer in src/node_file.cc + * See: https://github.com/nodejs/node/blob/e9ed113/src/node_file.cc#L1818 + * + * @param fs file descriptor + * @param buffer the data to write + * @param offset where in the buffer to start from + * @param length how much to write + * @param position if integer, position to write at in the file. if null, write from the current position + * @param context context object for passing error number + */ +export function writeBufferSync( + fd: number, + buffer: Uint8Array, + offset: number, + length: number, + position: number | null, + ctx: { errno?: number }, +) { + assert(offset >= 0, "offset should be greater or equal to 0"); + assert( + offset + length <= buffer.byteLength, + `buffer doesn't have enough data: byteLength = ${buffer.byteLength}, offset + length = ${offset + + length}`, + ); + if (position) { + Deno.seekSync(fd, position, Deno.SeekMode.Current); + } + const subarray = buffer.subarray(offset, offset + length); + try { + return Deno.writeSync(fd, subarray); + } catch (e) { + ctx.errno = extractOsErrorNumberFromErrorMessage(e); + return 0; + } +} + +function extractOsErrorNumberFromErrorMessage(e: Error): number { + const match = e.message.match(/\(os error (\d+)\)/); + if (match) { + return +match[1]; + } + return 255; // Unknown error +} diff --git a/node/internal_binding/fs_test.ts b/node/internal_binding/fs_test.ts new file mode 100644 index 000000000000..f1c12f85a069 --- /dev/null +++ b/node/internal_binding/fs_test.ts @@ -0,0 +1,52 @@ +// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. +import { writeBufferSync } from "./fs.ts"; +import { assertEquals } from "../../testing/asserts.ts"; + +Deno.test("[node/internal_binding/fs] writeBufferSync", async () => { + const tempfile = await Deno.makeTempFile(); + await Deno.writeTextFile(tempfile, "01234567890123456789"); + + const file = await Deno.open(tempfile, { write: true }); + await Deno.seek(file.rid, 5, Deno.SeekMode.Start); + + try { + const ctx: { errno?: number } = {}; + const bytesWritten = writeBufferSync( + file.rid, + new Uint8Array([65, 66, 67, 68, 69] /* abcde */), + 1, + 3, + 5, + ctx, + ); + + assertEquals(await Deno.readTextFile(tempfile), "0123456789BCD3456789"); + assertEquals(bytesWritten, 3); + assertEquals(typeof ctx.errno, "undefined"); + } finally { + Deno.close(file.rid); + Deno.remove(tempfile); + } +}); +Deno.test("[node/internal_binding/fs] writeBufferSync", async () => { + const tempfile = await Deno.makeTempFile(); + await Deno.writeTextFile(tempfile, "01234567890123456789"); + const file = await Deno.open(tempfile, { read: true, write: false }); + + try { + const ctx: { errno?: number } = {}; + const bytesWritten = writeBufferSync( + file.rid, + new Uint8Array([65, 66, 67, 68, 69] /* abcde */), + 1, + 3, + 5, + ctx, + ); + assertEquals(bytesWritten, 0); + assertEquals(ctx.errno, 9); + } finally { + Deno.close(file.rid); + Deno.remove(tempfile); + } +}); From 285f154063cab9370176708988edd13b4d527ed6 Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa <stibium121@gmail.com> Date: Thu, 29 Apr 2021 18:08:08 +0900 Subject: [PATCH 2/4] fix: fix lint --- node/internal_binding/fs.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/node/internal_binding/fs.ts b/node/internal_binding/fs.ts index 0aae7c98d4d5..a66bbafcebb1 100644 --- a/node/internal_binding/fs.ts +++ b/node/internal_binding/fs.ts @@ -16,12 +16,12 @@ import { assert } from "../../testing/asserts.ts"; * @param callback callback function */ export function writeBuffer( - fd: number, - buffer: Uint8Array, - offset: number, - length: number, - position: number | null, - callback?: (err: Error, n: number) => void, + _fd: number, + _buffer: Uint8Array, + _offset: number, + _length: number, + _position: number | null, + _callback?: (err: Error, n: number) => void, ): void { throw new Error("unimplemented!"); } From d5b960b4c5c2bd2471e874303e80470f4a96aec5 Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa <stibium121@gmail.com> Date: Fri, 30 Apr 2021 15:37:02 +0900 Subject: [PATCH 3/4] fix: fix errno in windows --- node/internal_binding/fs_test.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/node/internal_binding/fs_test.ts b/node/internal_binding/fs_test.ts index f1c12f85a069..297a3efa6794 100644 --- a/node/internal_binding/fs_test.ts +++ b/node/internal_binding/fs_test.ts @@ -44,7 +44,11 @@ Deno.test("[node/internal_binding/fs] writeBufferSync", async () => { ctx, ); assertEquals(bytesWritten, 0); - assertEquals(ctx.errno, 9); + if (Deno.build.os === "windows") { + assertEquals(ctx.errno, 5); // Access is denied + } else { + assertEquals(ctx.errno, 9); // Bad file descriptor + } } finally { Deno.close(file.rid); Deno.remove(tempfile); From caba10e984651490a8ca51d7973915eebdb83174 Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa <stibium121@gmail.com> Date: Fri, 30 Apr 2021 15:52:27 +0900 Subject: [PATCH 4/4] fix: fix Deno.remove call --- node/internal_binding/fs_test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/internal_binding/fs_test.ts b/node/internal_binding/fs_test.ts index 297a3efa6794..41f0ac9460b2 100644 --- a/node/internal_binding/fs_test.ts +++ b/node/internal_binding/fs_test.ts @@ -25,7 +25,7 @@ Deno.test("[node/internal_binding/fs] writeBufferSync", async () => { assertEquals(typeof ctx.errno, "undefined"); } finally { Deno.close(file.rid); - Deno.remove(tempfile); + await Deno.remove(tempfile); } }); Deno.test("[node/internal_binding/fs] writeBufferSync", async () => { @@ -51,6 +51,6 @@ Deno.test("[node/internal_binding/fs] writeBufferSync", async () => { } } finally { Deno.close(file.rid); - Deno.remove(tempfile); + await Deno.remove(tempfile); } });