Skip to content

Commit 72bc93f

Browse files
committed
Merge branch 'jep-9'
Closes #9. * jep-9: Pass final 3 tests Sync latest compliance tests from jmespath.test Implement jep-9: Improved filters Bump version to 0.12.0 Add support for JEP-12
2 parents e68a9f3 + 1a2a255 commit 72bc93f

File tree

13 files changed

+847
-227
lines changed

13 files changed

+847
-227
lines changed

artifacts/jmespath.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jmespath.js

Lines changed: 106 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,10 @@
119119
}
120120

121121

122-
// The "[", "<", ">" tokens
122+
// The "&", "[", "<", ">" tokens
123123
// are not in basicToken because
124124
// there are two token variants
125-
// ("[?", "<=", ">="). This is specially handled
125+
// ("&&", "[?", "<=", ">="). This is specially handled
126126
// below.
127127

128128
var basicTokens = {
@@ -135,8 +135,7 @@
135135
"]": "Rbracket",
136136
"(": "Lparen",
137137
")": "Rparen",
138-
"@": "Current",
139-
"&": "Expref"
138+
"@": "Current"
140139
};
141140

142141
var identifierStart = {
@@ -214,6 +213,12 @@
214213
tokens.push({type: "QuotedIdentifier",
215214
value: identifier,
216215
start: start});
216+
} else if (stream[this.current] === "'") {
217+
start = this.current;
218+
identifier = this.consumeRawStringLiteral(stream);
219+
tokens.push({type: "Literal",
220+
value: identifier,
221+
start: start});
217222
} else if (stream[this.current] === "`") {
218223
start = this.current;
219224
var literal = this.consumeLiteral(stream);
@@ -225,6 +230,15 @@
225230
} else if (skipChars[stream[this.current]] !== undefined) {
226231
// Ignore whitespace.
227232
this.current++;
233+
} else if (stream[this.current] === "&") {
234+
start = this.current;
235+
this.current++;
236+
if (stream[this.current] === "&") {
237+
this.current++;
238+
tokens.push({type: "And", value: "&&", start: start});
239+
} else {
240+
tokens.push({type: "Expref", value: "&", start: start});
241+
}
228242
} else if (stream[this.current] === "|") {
229243
start = this.current;
230244
this.current++;
@@ -271,6 +285,26 @@
271285
return JSON.parse(stream.slice(start, this.current));
272286
},
273287

288+
consumeRawStringLiteral: function(stream) {
289+
var start = this.current;
290+
this.current++;
291+
var maxLength = stream.length;
292+
while (stream[this.current] !== "'" && this.current < maxLength) {
293+
// You can escape a single quote and you can escape an escape.
294+
var current = this.current;
295+
if (stream[current] === "\\" && (stream[current + 1] === "\\" ||
296+
stream[current + 1] === "'")) {
297+
current += 2;
298+
} else {
299+
current++;
300+
}
301+
this.current = current;
302+
}
303+
this.current++;
304+
var literal = stream.slice(start + 1, this.current - 1);
305+
return literal.replace("\\'", "'");
306+
},
307+
274308
consumeNumber: function(stream) {
275309
var start = this.current;
276310
this.current++;
@@ -304,6 +338,8 @@
304338
if (stream[this.current] === "=") {
305339
this.current++;
306340
return {type: "NE", value: "!=", start: start};
341+
} else {
342+
return {type: "Not", value: "!", start: start};
307343
}
308344
} else if (startingChar === "<") {
309345
if (stream[this.current] === "=") {
@@ -394,17 +430,19 @@
394430
"Current": 0,
395431
"Expref": 0,
396432
"Pipe": 1,
397-
"EQ": 2,
398-
"GT": 2,
399-
"LT": 2,
400-
"GTE": 2,
401-
"LTE": 2,
402-
"NE": 2,
403-
"Or": 5,
404-
"Flatten": 6,
433+
"Or": 2,
434+
"And": 3,
435+
"EQ": 5,
436+
"GT": 5,
437+
"LT": 5,
438+
"GTE": 5,
439+
"LTE": 5,
440+
"NE": 5,
441+
"Flatten": 9,
405442
"Star": 20,
406-
"Filter": 20,
443+
"Filter": 21,
407444
"Dot": 40,
445+
"Not": 45,
408446
"Lbrace": 50,
409447
"Lbracket": 55,
410448
"Lparen": 60
@@ -505,11 +543,21 @@
505543
}
506544
},
507545

546+
nudNot: function() {
547+
var right = this.expression(this.bindingPower.Not);
548+
return {type: "NotExpression", children: [right]};
549+
},
550+
508551
ledOr: function(left) {
509552
var right = this.expression(this.bindingPower.Or);
510553
return {type: "OrExpression", children: [left, right]};
511554
},
512555

556+
ledAnd: function(left) {
557+
var right = this.expression(this.bindingPower.And);
558+
return {type: "AndExpression", children: [left, right]};
559+
},
560+
513561
ledPipe: function(left) {
514562
var right = this.expression(this.bindingPower.Pipe);
515563
return {type: "Pipe", children: [left, right]};
@@ -692,6 +740,22 @@
692740
return {type: "Projection", children: [leftNode, rightNode]};
693741
},
694742

743+
nudLparen: function() {
744+
var args = [];
745+
var expression;
746+
while (this.lookahead(0) !== "Rparen") {
747+
if (this.lookahead(0) === "Current") {
748+
expression = {type: "Current"};
749+
this.advance();
750+
} else {
751+
expression = this.expression(0);
752+
}
753+
args.push(expression);
754+
}
755+
this.match("Rparen");
756+
return args[0];
757+
},
758+
695759
ledLparen: function(left) {
696760
var name = left.name;
697761
var args = [];
@@ -965,7 +1029,7 @@
9651029
var matched, current;
9661030
for (var i = 0; i < base.length; i++) {
9671031
matched = this.visit(node.children[2], base[i]);
968-
if (matched === true) {
1032+
if (!isFalse(matched)) {
9691033
filtered.push(base[i]);
9701034
}
9711035
}
@@ -1060,6 +1124,20 @@
10601124
return matched;
10611125
},
10621126

1127+
visitAndExpression: function(node, value) {
1128+
var first = this.visit(node.children[0], value);
1129+
1130+
if (isFalse(first) === true) {
1131+
return first;
1132+
}
1133+
return this.visit(node.children[1], value);
1134+
},
1135+
1136+
visitNotExpression: function(node, value) {
1137+
var first = this.visit(node.children[0], value);
1138+
return isFalse(first);
1139+
},
1140+
10631141
visitLiteral: function(node) {
10641142
return node.value;
10651143
},
@@ -1119,6 +1197,9 @@
11191197
length: {
11201198
func: this.functionLength,
11211199
signature: [{types: ["string", "array", "object"]}]},
1200+
map: {
1201+
func: this.functionMap,
1202+
signature: [{types: ["expref"]}, {types: ["array"]}]},
11221203
max: {
11231204
func: this.functionMax,
11241205
signature: [{types: ["array-number", "array-string"]}]},
@@ -1334,6 +1415,17 @@
13341415
}
13351416
},
13361417

1418+
functionMap: function(resolvedArgs) {
1419+
var mapped = [];
1420+
var interpreter = this.interpreter;
1421+
var exprefNode = resolvedArgs[0];
1422+
var elements = resolvedArgs[1];
1423+
for (var i = 0; i < elements.length; i++) {
1424+
mapped.push(interpreter.visit(exprefNode, elements[i]));
1425+
}
1426+
return mapped;
1427+
},
1428+
13371429
functionMerge: function(resolvedArgs) {
13381430
var merged = {};
13391431
for (var i = 0; i < resolvedArgs.length; i++) {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "jmespath",
33
"description": "JMESPath implementation in javascript",
4-
"version": "0.11.0",
4+
"version": "0.12.0",
55
"author": {
66
"name": "James Saryerwinnie",
77
"email": "[email protected]",

test/compliance/basic.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
"expression": "foo.bar.baz",
1515
"result": "correct"
1616
},
17+
{
18+
"expression": "foo\n.\nbar\n.baz",
19+
"result": "correct"
20+
},
1721
{
1822
"expression": "foo.bar.baz.bad",
1923
"result": null

0 commit comments

Comments
 (0)