Skip to content

Commit 98ab760

Browse files
author
Chris Armstrong
committed
standardize error output
1 parent b16deb4 commit 98ab760

File tree

1 file changed

+42
-28
lines changed

1 file changed

+42
-28
lines changed

jmespath.js

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,19 @@
233233
ch === "_";
234234
}
235235

236+
function createErrorClass(className) {
237+
var ExtendedError = function (message) {
238+
Error.call(this, message);
239+
this.name = className;
240+
}
241+
ExtendedError.prototype = Object.create(Error.prototype);
242+
ExtendedError.prototype.constructor = ExtendedError;
243+
244+
return ExtendedError;
245+
}
246+
247+
var LexerError = createErrorClass("LexerError");
248+
236249
function Lexer() {
237250
}
238251
Lexer.prototype = {
@@ -304,8 +317,7 @@
304317
tokens.push({type: TOK_PIPE, value: "|", start: start});
305318
}
306319
} else {
307-
var error = new Error("Unknown character:" + stream[this._current]);
308-
error.name = "LexerError";
320+
var error = new LexerError("Unknown character:" + stream[this._current]);
309321
throw error;
310322
}
311323
}
@@ -500,6 +512,8 @@
500512
bindingPower[TOK_LBRACKET] = 55;
501513
bindingPower[TOK_LPAREN] = 60;
502514

515+
var ParserError = createErrorClass("ParserError");
516+
503517
function Parser() {
504518
}
505519

@@ -510,9 +524,8 @@
510524
var ast = this.expression(0);
511525
if (this._lookahead(0) !== TOK_EOF) {
512526
var t = this._lookaheadToken(0);
513-
var error = new Error(
527+
var error = new ParserError(
514528
"Unexpected token type: " + t.type + ", value: " + t.value);
515-
error.name = "ParserError";
516529
throw error;
517530
}
518531
return ast;
@@ -562,7 +575,7 @@
562575
case TOK_QUOTEDIDENTIFIER:
563576
var node = {type: "Field", name: token.value};
564577
if (this._lookahead(0) === TOK_LPAREN) {
565-
throw new Error("Quoted identifier not allowed for function names.");
578+
throw new ParserError("Quoted identifier not allowed for function names.");
566579
}
567580
return node;
568581
case TOK_NOT:
@@ -704,17 +717,15 @@
704717
this._advance();
705718
} else {
706719
var t = this._lookaheadToken(0);
707-
var error = new Error("Expected " + tokenType + ", got: " + t.type);
708-
error.name = "ParserError";
720+
var error = new ParserError("Expected " + tokenType + ", got: " + t.type);
709721
throw error;
710722
}
711723
},
712724

713725
_errorToken: function(token) {
714-
var error = new Error("Invalid token (" +
726+
var error = new ParserError("Invalid token (" +
715727
token.type + "): \"" +
716728
token.value + "\"");
717-
error.name = "ParserError";
718729
throw error;
719730
},
720731

@@ -759,9 +770,8 @@
759770
this._advance();
760771
} else {
761772
var t = this._lookahead(0);
762-
var error = new Error("Syntax error, unexpected token: " +
773+
var error = new ParserError("Syntax error, unexpected token: " +
763774
t.value + "(" + t.type + ")");
764-
error.name = "Parsererror";
765775
throw error;
766776
}
767777
currentToken = this._lookahead(0);
@@ -805,9 +815,8 @@
805815
right = this._parseDotRHS(rbp);
806816
} else {
807817
var t = this._lookaheadToken(0);
808-
var error = new Error("Sytanx error, unexpected token: " +
818+
var error = new ParserError("Syntax error, unexpected token: " +
809819
t.value + "(" + t.type + ")");
810-
error.name = "ParserError";
811820
throw error;
812821
}
813822
return right;
@@ -821,7 +830,7 @@
821830
if (this._lookahead(0) === TOK_COMMA) {
822831
this._match(TOK_COMMA);
823832
if (this._lookahead(0) === TOK_RBRACKET) {
824-
throw new Error("Unexpected token Rbracket");
833+
throw new ParserError("Unexpected token Rbracket");
825834
}
826835
}
827836
}
@@ -836,7 +845,7 @@
836845
for (;;) {
837846
keyToken = this._lookaheadToken(0);
838847
if (identifierTypes.indexOf(keyToken.type) < 0) {
839-
throw new Error("Expecting an identifier token, got: " +
848+
throw new ParserError("Expecting an identifier token, got: " +
840849
keyToken.type);
841850
}
842851
keyName = keyToken.value;
@@ -856,6 +865,7 @@
856865
}
857866
};
858867

868+
var InterpreterError = createErrorClass("InterpreterError");
859869

860870
function TreeInterpreter(runtime) {
861871
this.runtime = runtime;
@@ -997,7 +1007,7 @@
9971007
result = first <= second;
9981008
break;
9991009
default:
1000-
throw new Error("Unknown comparator: " + node.name);
1010+
throw new InterpreterError("Unknown comparator: " + node.name);
10011011
}
10021012
return result;
10031013
case TOK_FLATTEN:
@@ -1073,7 +1083,7 @@
10731083
refNode.jmespathType = TOK_EXPREF;
10741084
return refNode;
10751085
default:
1076-
throw new Error("Unknown node type: " + node.type);
1086+
throw new InterpreterError("Unknown node type: " + node.type);
10771087
}
10781088
},
10791089

@@ -1122,6 +1132,10 @@
11221132

11231133
};
11241134

1135+
var RuntimeError = createErrorClass("RuntimeError");
1136+
var ArgumentError = createErrorClass("ArgumentError");
1137+
var TypeMismatchError = createErrorClass("TypeMismatchError");
1138+
11251139
function Runtime(interpreter) {
11261140
this._interpreter = interpreter;
11271141
this.functionTable = {
@@ -1209,7 +1223,7 @@
12091223
callFunction: function(name, resolvedArgs) {
12101224
var functionEntry = this.functionTable[name];
12111225
if (functionEntry === undefined) {
1212-
throw new Error("Unknown function: " + name + "()");
1226+
throw new RuntimeError("Unknown function: " + name + "()");
12131227
}
12141228
this._validateArgs(name, resolvedArgs, functionEntry._signature);
12151229
return functionEntry._func.call(this, resolvedArgs);
@@ -1225,13 +1239,13 @@
12251239
if (signature[signature.length - 1].variadic) {
12261240
if (args.length < signature.length) {
12271241
pluralized = signature.length === 1 ? " argument" : " arguments";
1228-
throw new Error("ArgumentError: " + name + "() " +
1242+
throw new ArgumentError(name + "() " +
12291243
"takes at least" + signature.length + pluralized +
12301244
" but received " + args.length);
12311245
}
12321246
} else if (args.length !== signature.length) {
12331247
pluralized = signature.length === 1 ? " argument" : " arguments";
1234-
throw new Error("ArgumentError: " + name + "() " +
1248+
throw new ArgumentError(name + "() " +
12351249
"takes " + signature.length + pluralized +
12361250
" but received " + args.length);
12371251
}
@@ -1254,7 +1268,7 @@
12541268
return TYPE_NAME_TABLE[typeIdentifier];
12551269
})
12561270
.join(',');
1257-
throw new Error("TypeError: " + name + "() " +
1271+
throw new TypeMismatchError(name + "() " +
12581272
"expected argument " + (i + 1) +
12591273
" to be type " + expected +
12601274
" but received type " +
@@ -1547,7 +1561,7 @@
15471561
var requiredType = this._getTypeName(
15481562
interpreter.visit(exprefNode, sortedArray[0]));
15491563
if ([TYPE_NUMBER, TYPE_STRING].indexOf(requiredType) < 0) {
1550-
throw new Error("TypeError");
1564+
throw new TypeMismatchError("Array elements must be of type Number or String to sort");
15511565
}
15521566
var that = this;
15531567
// In order to get a stable sort out of an unstable
@@ -1565,12 +1579,12 @@
15651579
var exprA = interpreter.visit(exprefNode, a[1]);
15661580
var exprB = interpreter.visit(exprefNode, b[1]);
15671581
if (that._getTypeName(exprA) !== requiredType) {
1568-
throw new Error(
1569-
"TypeError: expected " + requiredType + ", received " +
1582+
throw new TypeMismatchError(
1583+
"expected " + requiredType + ", received " +
15701584
that._getTypeName(exprA));
15711585
} else if (that._getTypeName(exprB) !== requiredType) {
1572-
throw new Error(
1573-
"TypeError: expected " + requiredType + ", received " +
1586+
throw new TypeMismatchError(
1587+
"expected " + requiredType + ", received " +
15741588
that._getTypeName(exprB));
15751589
}
15761590
if (exprA > exprB) {
@@ -1631,9 +1645,9 @@
16311645
var keyFunc = function(x) {
16321646
var current = interpreter.visit(exprefNode, x);
16331647
if (allowedTypes.indexOf(that._getTypeName(current)) < 0) {
1634-
var msg = "TypeError: expected one of " + allowedTypes +
1648+
var msg = "expected one of " + allowedTypes +
16351649
", received " + that._getTypeName(current);
1636-
throw new Error(msg);
1650+
throw new TypeMismatchError(msg);
16371651
}
16381652
return current;
16391653
};

0 commit comments

Comments
 (0)