Skip to content

Commit

Permalink
Merge pull request #48 from badgateway/catch-type-error
Browse files Browse the repository at this point in the history
Checking for TypeError
  • Loading branch information
evert committed Aug 3, 2023
2 parents 6fbfe32 + 7dc8620 commit 30d25c3
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 25 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ name: Node.js CI

on:
push:
branches: [ main ]
branches: [ main, 'version/**' ]
pull_request:
branches: [ main ]
branches: [ main, 'version/**' ]

jobs:
build:
Expand Down
20 changes: 14 additions & 6 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
ChangeLog
=========

1.0.1 (????-??-??)
------------------

* This library emitted `TypeError` or a plain `Error` in a few places in the
parser, where it should have been `ParseError` this is corrected everywhere
now.


1.0.0 (2023-06-13)
------------------

Expand Down Expand Up @@ -84,9 +92,9 @@ ChangeLog
* First version!
* Parses all of the [04 draft of the specification][1].

[1]: https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-04 [2]:
https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-09 [3]:
https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-10 [4]:
https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-13 [5]:
https://datatracker.ietf.org/doc/html/rfc8941 [6]:
https://github.com/httpwg/structured-field-tests
[1]: https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-04
[2]: https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-09
[3]: https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-10
[4]: https://tools.ietf.org/html/draft-ietf-httpbis-header-structure-13
[5]: https://datatracker.ietf.org/doc/html/rfc8941
[6]: https://github.com/httpwg/structured-field-tests
18 changes: 12 additions & 6 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ export default class Parser {
private parseBareItem(): BareItem {

const char = this.lookChar();
if (char === undefined) {
throw new ParseError(this.pos, 'Unexpected end of string');
}
if (char.match(/^[-0-9]/)) {
return this.parseIntegerOrDecimal();
}
Expand Down Expand Up @@ -284,7 +287,7 @@ export default class Parser {
} else if (char === '"') {
return outputString;
} else if (!isAscii(char)) {
throw new Error('Strings must be in the ASCII range');
throw new ParseError(this.pos, 'Strings must be in the ASCII range');
} else {
outputString += char;
}
Expand All @@ -305,7 +308,7 @@ export default class Parser {

while(!this.eof()) {
const char = this.lookChar();
if (!/^[:/!#$%&'*+\-.^_`|~A-Za-z0-9]$/.test(char)) {
if (char===undefined || !/^[:/!#$%&'*+\-.^_`|~A-Za-z0-9]$/.test(char)) {
return new Token(outputString);
}
outputString += this.getChar();
Expand Down Expand Up @@ -352,15 +355,15 @@ export default class Parser {

private parseKey(): string {

if (!this.lookChar().match(/^[a-z*]/)) {
if (!this.lookChar()?.match(/^[a-z*]/)) {
throw new ParseError(this.pos, 'A key must begin with an asterisk or letter (a-z)');
}

let outputString = '';

while(!this.eof()) {
const char = this.lookChar();
if (!/^[a-z0-9_\-.*]$/.test(char)) {
if (char===undefined || !/^[a-z0-9_\-.*]$/.test(char)) {
return outputString;
}
outputString += this.getChar();
Expand All @@ -372,8 +375,10 @@ export default class Parser {

/**
* Looks at the next character without advancing the cursor.
*
* Returns undefined if we were at the end of the string.
*/
private lookChar():string {
private lookChar():string|undefined {

return this.input[this.pos];

Expand Down Expand Up @@ -436,8 +441,9 @@ export default class Parser {
}

const isDigitRegex = /^[0-9]$/;
function isDigit(char: string): boolean {
function isDigit(char: string|undefined): boolean {

if (char===undefined) return false;
return isDigitRegex.test(char);

}
41 changes: 30 additions & 11 deletions test/httpwg-tests.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
const expect = require('chai').expect;
const parser = require('../dist/parser');
const serializer = require('../dist/serializer');
const {
parseItem,
parseList,
parseDictionary,

serializeItem,
serializeList,
serializeDictionary,

ParseError,
} = require('../dist');
const { Token, ByteSequence } = require('../dist');
const base32Encode = require('base32-encode');
const base32Decode = require('base32-decode');
Expand Down Expand Up @@ -100,13 +109,13 @@ function makeParseTest(test) {
try {
switch(test.header_type) {
case 'item' :
result = parser.parseItem(input);
result = parseItem(input);
break;
case 'list' :
result = parser.parseList(input);
result = parseList(input);
break;
case 'dictionary' :
result = parser.parseDictionary(input);
result = parseDictionary(input);
break;
default:
throw new Error('Unsupported header type: ' + test.header_type);
Expand All @@ -118,13 +127,21 @@ function makeParseTest(test) {

if (test.must_fail) {
expect(hadError).to.equal(true, 'Parsing this should result in a failure');

if (!(caughtError instanceof ParseError)) {
console.error('Original error:');
console.error(caughtError);
throw new Error(
`Errors during the parsing phase should be of type "ParseError" We got: "${caughtError.constructor.name}"`,
{cause: caughtError}
);
}
} else {

if (hadError) {
// There was an error

if (test.can_fail) {
// Failure is OK
expect(hadError).to.equal(true);
expect(caughtError instanceof ParseError).to.equal(true);
} else {
// Failure is NOT OK
throw new Error('We should not have failed but got an error: ' + caughtError.message);
Expand Down Expand Up @@ -200,13 +217,13 @@ function makeSerializeTest(test) {
try {
switch(test.header_type) {
case 'item' :
output = serializer.serializeItem(unpackTestValue(input));
output = serializeItem(unpackTestValue(input));
break;
case 'list' :
output = serializer.serializeList(unpackTestValue(input));
output = serializeList(unpackTestValue(input));
break;
case 'dictionary' :
output = serializer.serializeDictionary(unpackDictionary(input));
output = serializeDictionary(unpackDictionary(input));
break;
default:
throw new Error('Unsupported header type: ' + test.header_type);
Expand All @@ -223,6 +240,7 @@ function makeSerializeTest(test) {
if (hadError) {
// There was an error
if (test.can_fail) {

// Failure is OK
expect(hadError).to.equal(true);
} else {
Expand All @@ -234,6 +252,7 @@ function makeSerializeTest(test) {
try {
expect(output).to.deep.equal(expected);
} catch (e) {

if (test.can_fail) {
// Optional failure
this.skip('can_fail was true');
Expand Down

0 comments on commit 30d25c3

Please sign in to comment.