From 4cba7ab81a30422ae2ef629d505596f3b24605a8 Mon Sep 17 00:00:00 2001 From: Anthony Dresser Date: Mon, 13 Jul 2020 09:43:58 -0700 Subject: [PATCH] Merge from vscode 17a8e253f69b01f0fa3ba4426ed873740682c666 (#11305) --- src/vs/platform/environment/node/stdin.ts | 5 ++- .../services/textfile/common/encoding.ts | 10 +++-- .../textFileService.io.test.ts | 39 ++++++++++++++++--- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/vs/platform/environment/node/stdin.ts b/src/vs/platform/environment/node/stdin.ts index c997051e87..7a32143d63 100644 --- a/src/vs/platform/environment/node/stdin.ts +++ b/src/vs/platform/environment/node/stdin.ts @@ -56,7 +56,10 @@ export async function readFromStdin(targetPath: string, verbose: boolean): Promi const decoder = iconv.getDecoder(encoding); process.stdin.on('data', chunk => stdinFileStream.write(decoder.write(chunk))); process.stdin.on('end', () => { - stdinFileStream.write(decoder.end()); + const end = decoder.end(); + if (typeof end === 'string') { + stdinFileStream.write(end); + } stdinFileStream.end(); }); process.stdin.on('error', error => stdinFileStream.destroy(error)); diff --git a/src/vs/workbench/services/textfile/common/encoding.ts b/src/vs/workbench/services/textfile/common/encoding.ts index 09b7c0fb7b..71e4e4fb5a 100644 --- a/src/vs/workbench/services/textfile/common/encoding.ts +++ b/src/vs/workbench/services/textfile/common/encoding.ts @@ -132,7 +132,7 @@ export async function toEncodeReadable(readable: Readable, encoding: str const iconv = await import('iconv-lite-umd'); const encoder = iconv.getEncoder(toNodeEncoding(encoding), options); - let bytesRead = 0; + let bytesWritten = false; let done = false; return { @@ -146,9 +146,9 @@ export async function toEncodeReadable(readable: Readable, encoding: str done = true; // If we are instructed to add a BOM but we detect that no - // bytes have been read, we must ensure to return the BOM + // bytes have been written, we must ensure to return the BOM // ourselves so that we comply with the contract. - if (bytesRead === 0 && options?.addBOM) { + if (!bytesWritten && options?.addBOM) { switch (encoding) { case UTF8: case UTF8_with_bom: @@ -162,13 +162,15 @@ export async function toEncodeReadable(readable: Readable, encoding: str const leftovers = encoder.end(); if (leftovers && leftovers.length > 0) { + bytesWritten = true; + return VSBuffer.wrap(leftovers); } return null; } - bytesRead += chunk.length; + bytesWritten = true; return VSBuffer.wrap(encoder.write(chunk)); } diff --git a/src/vs/workbench/services/textfile/test/electron-browser/textFileService.io.test.ts b/src/vs/workbench/services/textfile/test/electron-browser/textFileService.io.test.ts index b1d3744f83..48565794ca 100644 --- a/src/vs/workbench/services/textfile/test/electron-browser/textFileService.io.test.ts +++ b/src/vs/workbench/services/textfile/test/electron-browser/textFileService.io.test.ts @@ -20,7 +20,7 @@ import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemPro import { generateUuid } from 'vs/base/common/uuid'; import { join, basename } from 'vs/base/common/path'; import { getPathFromAmdModule } from 'vs/base/common/amd'; -import { UTF16be, UTF16le, UTF8_with_bom, UTF8 } from 'vs/workbench/services/textfile/common/encoding'; +import { UTF16be, UTF16le, UTF8_with_bom, UTF8, UTF16le_BOM, UTF16be_BOM, UTF8_BOM } from 'vs/workbench/services/textfile/common/encoding'; import { DefaultEndOfLine, ITextSnapshot } from 'vs/editor/common/model'; import { createTextModel } from 'vs/editor/test/common/editorTestUtils'; import { isWindows } from 'vs/base/common/platform'; @@ -84,7 +84,8 @@ suite('Files - TextFileService i/o', function () { await service.create(resource); - assert.equal(await exists(resource.fsPath), true); + const res = await readFile(resource.fsPath); + assert.equal(res.byteLength, 0 /* no BOM */); }); test('create - no encoding - content provided (string)', async () => { @@ -92,8 +93,9 @@ suite('Files - TextFileService i/o', function () { await service.create(resource, 'Hello World'); - assert.equal(await exists(resource.fsPath), true); - assert.equal((await readFile(resource.fsPath)).toString(), 'Hello World'); + const res = await readFile(resource.fsPath); + assert.equal(res.toString(), 'Hello World'); + assert.equal(res.byteLength, 'Hello World'.length); }); test('create - no encoding - content provided (snapshot)', async () => { @@ -101,8 +103,9 @@ suite('Files - TextFileService i/o', function () { await service.create(resource, stringToSnapshot('Hello World')); - assert.equal(await exists(resource.fsPath), true); - assert.equal((await readFile(resource.fsPath)).toString(), 'Hello World'); + const res = await readFile(resource.fsPath); + assert.equal(res.toString(), 'Hello World'); + assert.equal(res.byteLength, 'Hello World'.length); }); test('create - UTF 16 LE - no content', async () => { @@ -114,6 +117,9 @@ suite('Files - TextFileService i/o', function () { const detectedEncoding = await detectEncodingByBOM(resource.fsPath); assert.equal(detectedEncoding, UTF16le); + + const res = await readFile(resource.fsPath); + assert.equal(res.byteLength, UTF16le_BOM.length); }); test('create - UTF 16 LE - content provided', async () => { @@ -125,6 +131,9 @@ suite('Files - TextFileService i/o', function () { const detectedEncoding = await detectEncodingByBOM(resource.fsPath); assert.equal(detectedEncoding, UTF16le); + + const res = await readFile(resource.fsPath); + assert.equal(res.byteLength, 'Hello World'.length * 2 /* UTF16 2bytes per char */ + UTF16le_BOM.length); }); test('create - UTF 16 BE - no content', async () => { @@ -136,6 +145,9 @@ suite('Files - TextFileService i/o', function () { const detectedEncoding = await detectEncodingByBOM(resource.fsPath); assert.equal(detectedEncoding, UTF16be); + + const res = await readFile(resource.fsPath); + assert.equal(res.byteLength, UTF16le_BOM.length); }); test('create - UTF 16 BE - content provided', async () => { @@ -147,6 +159,9 @@ suite('Files - TextFileService i/o', function () { const detectedEncoding = await detectEncodingByBOM(resource.fsPath); assert.equal(detectedEncoding, UTF16be); + + const res = await readFile(resource.fsPath); + assert.equal(res.byteLength, 'Hello World'.length * 2 /* UTF16 2bytes per char */ + UTF16be_BOM.length); }); test('create - UTF 8 BOM - no content', async () => { @@ -158,6 +173,9 @@ suite('Files - TextFileService i/o', function () { const detectedEncoding = await detectEncodingByBOM(resource.fsPath); assert.equal(detectedEncoding, UTF8_with_bom); + + const res = await readFile(resource.fsPath); + assert.equal(res.byteLength, UTF8_BOM.length); }); test('create - UTF 8 BOM - content provided', async () => { @@ -169,6 +187,9 @@ suite('Files - TextFileService i/o', function () { const detectedEncoding = await detectEncodingByBOM(resource.fsPath); assert.equal(detectedEncoding, UTF8_with_bom); + + const res = await readFile(resource.fsPath); + assert.equal(res.byteLength, 'Hello World'.length + UTF8_BOM.length); }); test('create - UTF 8 BOM - empty content - snapshot', async () => { @@ -180,6 +201,9 @@ suite('Files - TextFileService i/o', function () { const detectedEncoding = await detectEncodingByBOM(resource.fsPath); assert.equal(detectedEncoding, UTF8_with_bom); + + const res = await readFile(resource.fsPath); + assert.equal(res.byteLength, UTF8_BOM.length); }); test('create - UTF 8 BOM - content provided - snapshot', async () => { @@ -191,6 +215,9 @@ suite('Files - TextFileService i/o', function () { const detectedEncoding = await detectEncodingByBOM(resource.fsPath); assert.equal(detectedEncoding, UTF8_with_bom); + + const res = await readFile(resource.fsPath); + assert.equal(res.byteLength, 'Hello World'.length + UTF8_BOM.length); }); test('write - use encoding (UTF 16 BE) - small content as string', async () => {