1'use strict';
2
3require('../common');
4const assert = require('assert');
5const { isUtf8, Buffer } = require('buffer');
6const { TextEncoder } = require('util');
7
8const encoder = new TextEncoder();
9
10assert.strictEqual(isUtf8(encoder.encode('hello')), true);
11assert.strictEqual(isUtf8(encoder.encode('ğ')), true);
12assert.strictEqual(isUtf8(Buffer.from([])), true);
13
14// Taken from test/fixtures/wpt/encoding/textdecoder-fatal.any.js
15[
16  [0xFF], // 'invalid code'
17  [0xC0], // 'ends early'
18  [0xE0], // 'ends early 2'
19  [0xC0, 0x00], // 'invalid trail'
20  [0xC0, 0xC0], // 'invalid trail 2'
21  [0xE0, 0x00], // 'invalid trail 3'
22  [0xE0, 0xC0], // 'invalid trail 4'
23  [0xE0, 0x80, 0x00], // 'invalid trail 5'
24  [0xE0, 0x80, 0xC0], // 'invalid trail 6'
25  [0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], // '> 0x10FFFF'
26  [0xFE, 0x80, 0x80, 0x80, 0x80, 0x80], // 'obsolete lead byte'
27
28  // Overlong encodings
29  [0xC0, 0x80], // 'overlong U+0000 - 2 bytes'
30  [0xE0, 0x80, 0x80], // 'overlong U+0000 - 3 bytes'
31  [0xF0, 0x80, 0x80, 0x80], // 'overlong U+0000 - 4 bytes'
32  [0xF8, 0x80, 0x80, 0x80, 0x80], // 'overlong U+0000 - 5 bytes'
33  [0xFC, 0x80, 0x80, 0x80, 0x80, 0x80], // 'overlong U+0000 - 6 bytes'
34
35  [0xC1, 0xBF], // 'overlong U+007F - 2 bytes'
36  [0xE0, 0x81, 0xBF], // 'overlong U+007F - 3 bytes'
37  [0xF0, 0x80, 0x81, 0xBF], // 'overlong U+007F - 4 bytes'
38  [0xF8, 0x80, 0x80, 0x81, 0xBF], // 'overlong U+007F - 5 bytes'
39  [0xFC, 0x80, 0x80, 0x80, 0x81, 0xBF], // 'overlong U+007F - 6 bytes'
40
41  [0xE0, 0x9F, 0xBF], // 'overlong U+07FF - 3 bytes'
42  [0xF0, 0x80, 0x9F, 0xBF], // 'overlong U+07FF - 4 bytes'
43  [0xF8, 0x80, 0x80, 0x9F, 0xBF], // 'overlong U+07FF - 5 bytes'
44  [0xFC, 0x80, 0x80, 0x80, 0x9F, 0xBF], // 'overlong U+07FF - 6 bytes'
45
46  [0xF0, 0x8F, 0xBF, 0xBF], // 'overlong U+FFFF - 4 bytes'
47  [0xF8, 0x80, 0x8F, 0xBF, 0xBF], // 'overlong U+FFFF - 5 bytes'
48  [0xFC, 0x80, 0x80, 0x8F, 0xBF, 0xBF], // 'overlong U+FFFF - 6 bytes'
49
50  [0xF8, 0x84, 0x8F, 0xBF, 0xBF], // 'overlong U+10FFFF - 5 bytes'
51  [0xFC, 0x80, 0x84, 0x8F, 0xBF, 0xBF], // 'overlong U+10FFFF - 6 bytes'
52
53  // UTF-16 surrogates encoded as code points in UTF-8
54  [0xED, 0xA0, 0x80], // 'lead surrogate'
55  [0xED, 0xB0, 0x80], // 'trail surrogate'
56  [0xED, 0xA0, 0x80, 0xED, 0xB0, 0x80], // 'surrogate pair'
57].forEach((input) => {
58  assert.strictEqual(isUtf8(Buffer.from(input)), false);
59});
60
61[
62  null,
63  undefined,
64  'hello',
65  true,
66  false,
67].forEach((input) => {
68  assert.throws(
69    () => { isUtf8(input); },
70    {
71      code: 'ERR_INVALID_ARG_TYPE',
72    },
73  );
74});
75
76{
77  // Test with detached array buffers
78  const arrayBuffer = new ArrayBuffer(1024);
79  structuredClone(arrayBuffer, { transfer: [arrayBuffer] });
80  assert.throws(
81    () => { isUtf8(arrayBuffer); },
82    {
83      code: 'ERR_INVALID_STATE'
84    }
85  );
86}
87