Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

jora

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jora - npm Package Compare versions

Comparing version 1.0.0-beta.4 to 1.0.0-beta.5

src/lang/nodes/Template.js

15

CHANGELOG.md

@@ -0,1 +1,16 @@

## 1.0.0-beta.5 (November 10, 2020)
- Jora became a superset of JSON5 (see #23)
- Added support for template literals
- Added support for multi-line comments
- Added support for hexadecimal numbers
- Added support for hexadecimal escape sequence in strings, i.e. `'hello\x20world'`
- Added support for multiple lines in strings by escaping new line characters
- Added `Infinity` and `NaN` literals
- Fixed string literal parsing to be ECMA-262 compliant
- Changed parsing to recognize line terminators according to ECMA-262 (added `\r\n`, `\u2028` and `\u2029`)
- Allowed a single trailing comma in object and array literals
- Allowed unicode escape sequence in identifier name
- Allowed object literal property names starting with `$` when a value is defined
## 1.0.0-beta.4 (November 4, 2020)

@@ -2,0 +17,0 @@

6

package.json
{
"name": "jora",
"version": "1.0.0-beta.4",
"version": "1.0.0-beta.5",
"description": "JavaScript object query engine",

@@ -43,3 +43,3 @@ "author": "Roman Dvornov <rdvornov@gmail.com> (https://github.com/lahmatiy)",

"eslint": "^6.5.1",
"jison": "^0.4.18",
"@lahmatiy/jison": "^0.4.18-remastered.1",
"mocha": "^6.2.3",

@@ -51,3 +51,3 @@ "nyc": "^14.1.0",

"engines": {
"node": ">=8.0.0"
"node": ">=8.10.0"
},

@@ -54,0 +54,0 @@ "files": [

@@ -54,2 +54,3 @@ # Jora

- [Syntax](#syntax)
- [Comments](#comments)
- [Primitives](#primitives)

@@ -98,6 +99,4 @@ - [Keywords](#keywords)

// or with custom methods
const queryWithCustomMethods = jora('foo.myMethod()', {
methods: {
myMethod(current) { /* do something and return a new value */ }
}
const queryWithCustomMethods = jora.setup({
myMethod(current) { /* do something and return a new value */ }
});

@@ -107,2 +106,3 @@

const result = query(data, context);
const result = queryWithCustomMethods('foo.myMethod()')(data, context);
```

@@ -204,2 +204,10 @@

### Comments
```
// single-line comment
/* multi-line
comment */
```
### Primitives

@@ -210,3 +218,5 @@

42<br>-123<br>4.22<br>1e3<br>1e-2 | Numbers
0xdecaf<br>-0xC0FFEE | Hexadecimal numbers
"string"<br>'string' | Strings
\`template line1<br>template line2\`<br>\`template ${hello} ${world}` | Template
/regexp/<br>/regexp/i | A JavaScript regexp, only `i` flag supported

@@ -229,2 +239,4 @@ { } | Object initializer/literal syntax. Spread operator (`...`) can be used, e.g. `{ a: 1, ..., ...foo }` (`...` with no expression on right side the same as `...$`)

- `undefined`
- `Infinity`
- `NaN`

@@ -231,0 +243,0 @@ ### Operators

@@ -24,6 +24,6 @@ const { isPlainObject } = require('../utils');

Object,
ObjectEntry,
Parentheses,
Pick,
Pipeline,
ObjectEntry,
Reference,

@@ -33,2 +33,3 @@ SliceNotation,

Spread,
Template,
Unary

@@ -41,2 +42,3 @@ } = require('./nodes').build;

const $1name = { name: '$1.name' };
const $$1name = { name: '"$" + $1.name' };
const $2 = { name: '$2' };

@@ -48,3 +50,3 @@ const $3 = { name: '$3' };

const $r1 = { name: '@1.range' };
const refs = new Set([$0, $1, $1name, $2, $3, $4, $5, $r0, $r1]);
const refs = new Set([$0, $1, $1name, $$1name, $2, $3, $4, $5, $r0, $r1]);
const asis = '';

@@ -108,6 +110,24 @@

const switchToPreventPrimitiveState = 'if (this._input) this.begin("preventPrimitive"); ';
const openScope = 'this.fnOpenedStack.push(this.fnOpened); this.fnOpened = 0; ';
const closeScope = 'this.fnOpened = this.fnOpenedStack.pop() || 0; ';
const templateToken = (input, state) => {
if (input[0] !== (state === 'template' ? '}' : '`')) {
return null;
}
for (let i = 1; i < input.length; i++) {
if (input[i] === '`') {
return i + 1;
}
if (input[i] === '$' && input[i + 1] === '{') {
return i + 2;
}
if (input[i] === '\\') {
i++;
}
}
return null;
};
module.exports = {

@@ -123,13 +143,14 @@ // Lexical tokens

ws: '\\s+', // required whitespaces
comment: '//.*?(\\r|\\n|$)',
ident: '[a-zA-Z_][a-zA-Z_$0-9]*',
comment: '//.*?(?:\\n|\\r\\n?|\\u2028|\\u2029|$)|/\\*(?:.|\\s)*?(?:\\*/|$)',
ident: '(?:[a-zA-Z_]|\\\\u[0-9a-fA-F]{4})(?:[a-zA-Z_$0-9]|\\\\u[0-9a-fA-F]{4})*',
rx: '/(?:\\\\.|[^/])+/i?'
},
startConditions: {
preventPrimitive: 0
preventPrimitive: 0,
template: 1
},
rules: [
// ignore comments and whitespaces
['{comment}', 'yy.commentRanges.push(yylloc.range); /* a comment */'],
['{ws}', '/* a whitespace */'],
['{comment}', 'yy.commentRanges.push(yylloc.range)'],
['{ws}', ''],

@@ -142,14 +163,49 @@ // hack to prevent primitive (i.e. regexp and function) consumption

// should be fixed in `regexp-lexer`
[['preventPrimitive'], '', 'this.done = false; this.popState();'],
[['preventPrimitive'], '', () => {
this.done = false;
this.popState();
}],
// template
[templateToken, (yy, yytext) => {
const token = yytext.endsWith('`') ? 'TEMPLATE' : 'TPL_START';
yytext = this.toStringLiteral(yytext, true, 1 + (token !== 'TEMPLATE'));
if (token === 'TEMPLATE') {
yy.pps();
}
return token;
}],
[['template'], templateToken, (yy, yytext) => {
const token = yytext.endsWith('`') ? 'TPL_END' : 'TPL_CONTINUE';
yytext = this.toStringLiteral(yytext, true, 1 + (token !== 'TPL_END'));
this.popState();
if (token === 'TPL_END') {
yy.pps();
}
return token;
}],
[['template'], '', () => this.parseError('Unexpected end of input')],
// braces
['\\(', openScope + 'return "(";'],
['\\)', closeScope + switchToPreventPrimitiveState + 'return ")";'],
['\\[', openScope + 'return "[";'],
['\\]', closeScope + switchToPreventPrimitiveState + 'return "]";'],
['\\{', openScope + 'return "{";'],
['\\}', closeScope + switchToPreventPrimitiveState + 'return "}";'],
['\\(', 'return "(";'],
['\\)', 'yy.pps(); return ")";'],
['\\[', 'return "[";'],
['\\]', 'yy.pps(); return "]";'],
['\\{', 'return "{";'],
['\\}', (yy) => {
if (this.bracketStack[this.bracketStack.length - 1] !== 'TPL_END') {
yy.pps();
return '}';
}
this.unput('}');
this.begin('template');
}],
// keywords (should goes before ident)
['(true|false|null|undefined){wb}', 'yytext = this.toLiteral(yytext);return "LITERAL";'],
// eslint-disable-next-line no-unused-vars
['(true|false|null|undefined|Infinity|NaN){wb}', (yytext) => {
yytext = this.toLiteral(yytext);
return 'LITERAL';
}],

@@ -167,18 +223,22 @@ // keyword operators (should goes before IDENT)

// primitives
['(\\d+\\.|\\.)?\\d+([eE][-+]?\\d+)?{wb}', switchToPreventPrimitiveState + 'yytext = Number(yytext); return "NUMBER";'], // 212.321
['"(?:\\\\.|[^"])*"', switchToPreventPrimitiveState + 'yytext = this.toStringLiteral(yytext); return "STRING";'], // "foo" "with \" escaped"
["'(?:\\\\.|[^'])*'", switchToPreventPrimitiveState + 'yytext = this.toStringLiteral(yytext); return "STRING";'], // 'foo' 'with \' escaped'
['{rx}', switchToPreventPrimitiveState + 'yytext = this.toRegExp(yytext); return "REGEXP";'], // /foo/i
['{ident}', switchToPreventPrimitiveState + 'return "IDENT";'], // foo123
['\\${ident}', switchToPreventPrimitiveState + 'yytext = yytext.slice(1); return "$IDENT";'], // $foo123
['(\\d+\\.|\\.)?\\d+([eE][-+]?\\d+)?{wb}', 'yy.pps(); yytext = Number(yytext); return "NUMBER";'], // 212.321
['0[xX][0-9a-fA-F]+', 'yy.pps(); yytext = parseInt(yytext, 16); return "NUMBER";'], // 0x12ab
['"(?:\\\\[\\\\"]|[^"])*"', 'yy.pps(); yytext = this.toStringLiteral(yytext); return "STRING";'], // "foo" "with \" escaped"
["'(?:\\\\[\\\\']|[^'])*'", 'yy.pps(); yytext = this.toStringLiteral(yytext); return "STRING";'], // 'foo' 'with \' escaped'
['{rx}', 'yy.pps(); yytext = this.toRegExp(yytext); return "REGEXP";'], // /foo/i
['{ident}', 'yy.pps(); yytext = this.ident(yytext); return "IDENT";'], // foo123
['\\${ident}', 'yy.pps(); yytext = this.ident(yytext.slice(1)); return "$IDENT";'], // $foo123
// special vars
['@', switchToPreventPrimitiveState + 'return "@";'],
['#', switchToPreventPrimitiveState + 'return "#";'],
['\\${2}', switchToPreventPrimitiveState + 'return "$$";'],
['\\$', switchToPreventPrimitiveState + 'return "$";'],
['@', 'yy.pps(); return "@";'],
['#', 'yy.pps(); return "#";'],
['\\$\\$', 'yy.pps(); return "$$";'],
['\\$', 'yy.pps(); return "$";'],
// functions
['=>', 'return "FUNCTION";'],
['<(?!=)', 'this.fnOpened++; return "FUNCTION_START"'],
['<(?!=)', () => {
this.fnOpened++;
return 'FUNCTION_START';
}],

@@ -192,15 +252,15 @@ // operators

['<', 'return "<";'],
['>', `
['>', () => {
if (this.fnOpened) {
this.fnOpened--;
return "FUNCTION_END";
return 'FUNCTION_END';
}
return ">";
`],
['\\.\\.\\(', openScope + 'return "..(";'],
['\\.\\(', openScope + 'return ".(";'],
['\\.\\[', openScope + 'return ".[";'],
return '>';
}],
['\\.\\.\\(', 'return "..(";'],
['\\.\\(', 'return ".(";'],
['\\.\\[', 'return ".[";'],
['\\.\\.\\.', 'return "...";'],
['\\.\\.', switchToPreventPrimitiveState + 'return "..";'],
['\\.', switchToPreventPrimitiveState + 'return ".";'],
['\\.\\.', 'yy.pps(); return "..";'],
['\\.', 'yy.pps(); return ".";'],
['\\?', 'return "?";'],

@@ -336,2 +396,3 @@ [',', 'return ",";'],

['LITERAL', $$(Literal($1))],
['template', $$(Template($1))],
['object', asis],

@@ -373,13 +434,30 @@ ['array', asis],

template: [
['templateString', $$([$1])],
['templateStart templateTail', '$$=[$1, ...$2]']
],
templateTail: [
['templateEnd', $$([null, $1])],
['e templateEnd', $$([$1, $2])],
['templateContinue templateTail', '$$=[null, $1, ...$2]'],
['e templateContinue templateTail', '$$=[$1, $2, ...$3]']
],
templateString: [['TEMPLATE', $$(Literal($1))]],
templateStart: [['TPL_START', $$(Literal($1))]],
templateContinue: [['TPL_CONTINUE', $$(Literal($1))]],
templateEnd: [['TPL_END', $$(Literal($1))]],
object: [
['{ }', $$(Object([]))],
['{ properties }', $$(Object($2))],
['{ properties , }', $$(Object($2))],
['{ definitions }', $$(Object([]))],
['{ definitions properties }', $$(Block($2, Object($3)))]
['{ definitions properties }', $$(Block($2, Object($3)))],
['{ definitions properties , }', $$(Block($2, Object($3)))]
],
properties: createCommaList('properties', 'property'),
property: [
['ident', $$(ObjectEntry($1, null))],
['$', $$(ObjectEntry(Current(), null))], // do nothing, but collect stat (suggestions)
['$ident', $$(ObjectEntry(Reference($1), null))],
['ident', $$(ObjectEntry($1, null))],
['ident : e', $$(ObjectEntry($1, $3))],

@@ -389,2 +467,3 @@ ['STRING : e', $$(ObjectEntry(Literal($1), $3))],

['LITERAL : e', $$(ObjectEntry(Literal($1), $3))],
['$ident : e', $$(ObjectEntry(Identifier($$1name), $3))],
['[ e ] : e', $$(ObjectEntry($2, $5))],

@@ -403,3 +482,4 @@ ['...', $$(Spread(null))],

['[ ]', $$(Array([]))],
['[ arrayElements ]', $$(Array($2))]
['[ arrayElements ]', $$(Array($2))],
['[ arrayElements , ]', $$(Array($2))]
],

@@ -406,0 +486,0 @@

@@ -31,2 +31,3 @@ const nodes = {

Spread: require('./Spread'),
Template: require('./Template'),
Unary: require('./Unary')

@@ -33,0 +34,0 @@ };

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc