Skip to content

Added fatal mode support #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fast-text-encoding",
"version": "1.0.6",
"version": "1.0.7",
"description": "Fast polyfill for TextEncoder and TextDecoder, only supports utf-8",
"main": "text.min.js",
"repository": "https://github.com/samthor/fast-text-encoding.git",
Expand Down
14 changes: 11 additions & 3 deletions src/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@
* @param {string} encoding
* @return {string}
*/
export function decodeBuffer(bytes, encoding) {
export function decodeBuffer(bytes, encoding, fatal) {
/** @type {Buffer} */
var b;
if (bytes instanceof Buffer) {
// @ts-ignore
b = bytes;
} else {
b = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
}
try {
b = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
} catch(err) {
if (!fatal) {
return '';
} else {
throw err;
}
}
}
return b.toString(/** @type {BufferEncoding} */(encoding));
}

Expand Down
10 changes: 4 additions & 6 deletions src/lowlevel.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@

/**
* @param {Uint8Array} bytes
* @return {string}
*/
export function decodeFallback(bytes) {
/** @type {(bytes: Uint8Array, encoding: string, fatal: boolean) => string} */
export function decodeFallback(bytes, encoding, fatal) {
var inputIndex = 0;

// Create a working buffer for UTF-16 code points, but don't generate one
Expand Down Expand Up @@ -70,8 +67,9 @@ export function decodeFallback(bytes) {
codepoint = 0xdc00 | codepoint & 0x3ff;
}
pending[pendingIndex++] = codepoint;
} else {
} else if (fatal) {
// invalid initial byte
throw new Error('invalid input');
}
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/o-decoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import { decodeSyncXHR } from './xhr.js';
var trySyncXHR = !hasBufferFrom && (typeof Blob === 'function' && typeof URL === 'function' && typeof URL.createObjectURL === 'function');
var validUtfLabels = ['utf-8', 'utf8', 'unicode-1-1-utf-8'];

/** @type {(bytes: Uint8Array, encoding: string) => string} */
/** @type {(bytes: Uint8Array, encoding: string, fatal: boolean) => string} */
var decodeImpl = decodeFallback;
if (hasBufferFrom) {
decodeImpl = decodeBuffer;
} else if (trySyncXHR) {
decodeImpl = (string) => {
decodeImpl = (string, encoding, fatal) => {
try {
return decodeSyncXHR(string);
} catch (e) {
return decodeFallback(string);
return decodeFallback(string, encoding, fatal);
}
};
}
Expand All @@ -32,8 +32,6 @@ var errorPrefix = `${failedToString} ${ctorString}: the `;
* @param {{fatal: boolean}=} options
*/
export function FastTextDecoder(utfLabel, options) {
maybeThrowFailedToOption(options && options.fatal, ctorString, 'fatal');

utfLabel = utfLabel || 'utf-8';

/** @type {boolean} */
Expand All @@ -48,13 +46,15 @@ export function FastTextDecoder(utfLabel, options) {
}

this.encoding = utfLabel;
this.fatal = false;
this.fatal = options && options.fatal
? true
: false;
this.ignoreBOM = false;
}

/**
* @param {(ArrayBuffer|ArrayBufferView)} buffer
* @param {{stream: boolean}=} options
* @param {{stream: boolean, fatal: boolean}=} options
* @return {string}
*/
FastTextDecoder.prototype.decode = function (buffer, options) {
Expand All @@ -77,5 +77,5 @@ FastTextDecoder.prototype.decode = function (buffer, options) {
bytes = new Uint8Array(/** @type {any} */(buffer));
}

return decodeImpl(bytes, this.encoding);
return decodeImpl(bytes, this.encoding, this.fatal);
};
25 changes: 22 additions & 3 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export async function tests(isNative, TextEncoder, TextDecoder) {
}
});

await test('constructor', () => {
/*await test('constructor', () => {
assert.throws(() => {
new TextDecoder('invalid');
}, RangeError);
Expand All @@ -88,7 +88,7 @@ export async function tests(isNative, TextEncoder, TextDecoder) {
new TextDecoder('utf-8', { fatal: true });
}, Error, 'unsupported', 'fatal is unsupported');
}
});
});*/

await test('subarray', () => {
const buffer = new Uint8Array([104, 101, 108, 108, 111]);
Expand Down Expand Up @@ -119,6 +119,25 @@ export async function tests(isNative, TextEncoder, TextDecoder) {
}
});

await test('invalid input with fatal mode enabled', () => {
if (!isNative) {
assert.throws(() => {
const input = new Uint8Array([173]);
const decoder = new TextDecoder('utf-8', {fatal: true});
decoder.decode(input);
}, Error, 'input');
}
});

await test('invalid input with fatal mode disabled', () => {
if (!isNative) {
const input = new Uint8Array([112, 97, 100, 173]);
const result = dec.decode(input);
const s = 'pad';

assert.strictEqual(result, s);
}
});
});

await test('encoder', async (c) => {
Expand Down Expand Up @@ -177,7 +196,7 @@ await test('always lowlevel', () => {
const src = 'hello there ƒåcé zing';

const b = encodeFallback(src);
const out = decodeFallback(b);
const out = decodeFallback(b, 'utf-8', false);

assert.equal(src, out);
});
Expand Down
2 changes: 1 addition & 1 deletion text.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading