• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Flags: --expose-internals
2
3// This tests Node.js-specific behaviors of TextDecoder
4
5'use strict';
6
7const common = require('../common');
8
9const assert = require('assert');
10const { customInspectSymbol: inspect } = require('internal/util');
11const util = require('util');
12
13const buf = Buffer.from([0xef, 0xbb, 0xbf, 0x74, 0x65,
14                         0x73, 0x74, 0xe2, 0x82, 0xac]);
15
16// Make Sure TextDecoder exist
17assert(TextDecoder);
18
19// Test TextDecoder, UTF-8, fatal: false, ignoreBOM: false
20{
21  ['unicode-1-1-utf-8', 'utf8', 'utf-8'].forEach((i) => {
22    const dec = new TextDecoder(i);
23    assert.strictEqual(dec.encoding, 'utf-8');
24    const res = dec.decode(buf);
25    assert.strictEqual(res, 'test€');
26  });
27
28  ['unicode-1-1-utf-8', 'utf8', 'utf-8'].forEach((i) => {
29    const dec = new TextDecoder(i);
30    let res = '';
31    res += dec.decode(buf.slice(0, 8), { stream: true });
32    res += dec.decode(buf.slice(8));
33    assert.strictEqual(res, 'test€');
34  });
35}
36
37// Test TextDecoder, UTF-8, fatal: false, ignoreBOM: true
38{
39  ['unicode-1-1-utf-8', 'utf8', 'utf-8'].forEach((i) => {
40    const dec = new TextDecoder(i, { ignoreBOM: true });
41    const res = dec.decode(buf);
42    assert.strictEqual(res, '\ufefftest€');
43  });
44
45  ['unicode-1-1-utf-8', 'utf8', 'utf-8'].forEach((i) => {
46    const dec = new TextDecoder(i, { ignoreBOM: true });
47    let res = '';
48    res += dec.decode(buf.slice(0, 8), { stream: true });
49    res += dec.decode(buf.slice(8));
50    assert.strictEqual(res, '\ufefftest€');
51  });
52}
53
54// Test TextDecoder, UTF-8, fatal: true, ignoreBOM: false
55if (common.hasIntl) {
56  ['unicode-1-1-utf-8', 'utf8', 'utf-8'].forEach((i) => {
57    const dec = new TextDecoder(i, { fatal: true });
58    assert.throws(() => dec.decode(buf.slice(0, 8)),
59                  {
60                    code: 'ERR_ENCODING_INVALID_ENCODED_DATA',
61                    name: 'TypeError',
62                    message: 'The encoded data was not valid ' +
63                          'for encoding utf-8'
64                  });
65  });
66
67  ['unicode-1-1-utf-8', 'utf8', 'utf-8'].forEach((i) => {
68    const dec = new TextDecoder(i, { fatal: true });
69    dec.decode(buf.slice(0, 8), { stream: true });
70    dec.decode(buf.slice(8));
71  });
72} else {
73  assert.throws(
74    () => new TextDecoder('utf-8', { fatal: true }),
75    {
76      code: 'ERR_NO_ICU',
77      name: 'TypeError',
78      message: '"fatal" option is not supported on Node.js compiled without ICU'
79    });
80}
81
82// Test TextDecoder, label undefined, options null
83{
84  const dec = new TextDecoder(undefined, null);
85  assert.strictEqual(dec.encoding, 'utf-8');
86  assert.strictEqual(dec.fatal, false);
87  assert.strictEqual(dec.ignoreBOM, false);
88}
89
90// Test TextDecoder, UTF-16le
91{
92  const dec = new TextDecoder('utf-16le');
93  const res = dec.decode(Buffer.from('test€', 'utf-16le'));
94  assert.strictEqual(res, 'test€');
95}
96
97// Test TextDecoder, UTF-16be
98if (common.hasIntl) {
99  const dec = new TextDecoder('utf-16be');
100  const res = dec.decode(Buffer.from('test€', 'utf-16le').swap16());
101  assert.strictEqual(res, 'test€');
102}
103
104// Test TextDecoder inspect with hidden fields
105{
106  const dec = new TextDecoder('utf-8', { ignoreBOM: true });
107  if (common.hasIntl) {
108    assert.strictEqual(
109      util.inspect(dec, { showHidden: true }),
110      'TextDecoder {\n' +
111      '  encoding: \'utf-8\',\n' +
112      '  fatal: false,\n' +
113      '  ignoreBOM: true,\n' +
114      '  [Symbol(flags)]: 4,\n' +
115      '  [Symbol(handle)]: Converter {}\n' +
116      '}'
117    );
118  } else {
119    assert.strictEqual(
120      util.inspect(dec, { showHidden: true }),
121      'TextDecoder {\n' +
122      "  encoding: 'utf-8',\n" +
123      '  fatal: false,\n' +
124      '  ignoreBOM: true,\n' +
125      '  [Symbol(flags)]: 4,\n' +
126      '  [Symbol(handle)]: StringDecoder {\n' +
127      "    encoding: 'utf8',\n" +
128      '    [Symbol(kNativeDecoder)]: <Buffer 00 00 00 00 00 00 01>,\n' +
129      '    lastChar: [Getter],\n' +
130      '    lastNeed: [Getter],\n' +
131      '    lastTotal: [Getter]\n' +
132      '  }\n' +
133      '}'
134    );
135  }
136}
137
138
139// Test TextDecoder inspect without hidden fields
140{
141  const dec = new TextDecoder('utf-8', { ignoreBOM: true });
142  assert.strictEqual(
143    util.inspect(dec, { showHidden: false }),
144    'TextDecoder { encoding: \'utf-8\', fatal: false, ignoreBOM: true }'
145  );
146}
147
148// Test TextDecoder inspect with negative depth
149{
150  const dec = new TextDecoder();
151  assert.strictEqual(util.inspect(dec, { depth: -1 }), '[TextDecoder]');
152}
153
154{
155  const inspectFn = TextDecoder.prototype[inspect];
156  const decodeFn = TextDecoder.prototype.decode;
157  const {
158    encoding: { get: encodingGetter },
159    fatal: { get: fatalGetter },
160    ignoreBOM: { get: ignoreBOMGetter },
161  } = Object.getOwnPropertyDescriptors(TextDecoder.prototype);
162
163  const instance = new TextDecoder();
164
165  const expectedError = {
166    code: 'ERR_INVALID_THIS',
167    name: 'TypeError',
168    message: 'Value of "this" must be of type TextDecoder'
169  };
170
171  inspectFn.call(instance, Infinity, {});
172  decodeFn.call(instance);
173  encodingGetter.call(instance);
174  fatalGetter.call(instance);
175  ignoreBOMGetter.call(instance);
176
177  const invalidThisArgs = [{}, [], true, 1, '', new TextEncoder()];
178  invalidThisArgs.forEach((i) => {
179    assert.throws(() => inspectFn.call(i, Infinity, {}), expectedError);
180    assert.throws(() => decodeFn.call(i), expectedError);
181    assert.throws(() => encodingGetter.call(i), expectedError);
182    assert.throws(() => fatalGetter.call(i), expectedError);
183    assert.throws(() => ignoreBOMGetter.call(i), expectedError);
184  });
185}
186
187{
188  assert.throws(
189    () => new TextDecoder('utf-8', 1),
190    {
191      code: 'ERR_INVALID_ARG_TYPE',
192      name: 'TypeError'
193    }
194  );
195}
196