1'use strict'; 2// Flags: --expose-internals 3 4const common = require('../common'); 5const tmpdir = require('../common/tmpdir'); 6 7// The following tests validate aggregate errors are thrown correctly 8// when both an operation and close throw. 9 10const path = require('path'); 11const { 12 readFile, 13 writeFile, 14 truncate, 15 lchmod, 16} = require('fs/promises'); 17const { 18 FileHandle, 19} = require('internal/fs/promises'); 20 21const assert = require('assert'); 22const originalFd = Object.getOwnPropertyDescriptor(FileHandle.prototype, 'fd'); 23 24let count = 0; 25async function createFile() { 26 const filePath = path.join(tmpdir.path, `close_errors_${++count}.txt`); 27 await writeFile(filePath, 'content'); 28 return filePath; 29} 30 31async function checkCloseError(op) { 32 try { 33 const filePath = await createFile(); 34 Object.defineProperty(FileHandle.prototype, 'fd', { 35 get: function() { 36 // Close is set by using a setter, 37 // so it needs to be set on the instance. 38 const originalClose = this.close; 39 this.close = async () => { 40 // close the file 41 await originalClose.call(this); 42 const closeError = new Error('CLOSE_ERROR'); 43 closeError.code = 456; 44 throw closeError; 45 }; 46 return originalFd.get.call(this); 47 } 48 }); 49 50 await assert.rejects(op(filePath), { 51 name: 'Error', 52 message: 'CLOSE_ERROR', 53 code: 456, 54 }); 55 } finally { 56 Object.defineProperty(FileHandle.prototype, 'fd', originalFd); 57 } 58} 59(async function() { 60 tmpdir.refresh(); 61 await checkCloseError((filePath) => truncate(filePath)); 62 await checkCloseError((filePath) => readFile(filePath)); 63 await checkCloseError((filePath) => writeFile(filePath, '123')); 64 if (common.isOSX) { 65 await checkCloseError((filePath) => lchmod(filePath, 0o777)); 66 } 67})().then(common.mustCall()); 68