fix handling of reserved keywords when parsing (#4390)

pull/4395/head
Conduitry 4 years ago committed by GitHub
parent 2195832ecc
commit f5f489984f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -6,6 +6,8 @@
* Improve parsing error messages when there is a pending unclosed tag ([#4131](https://github.com/sveltejs/svelte/issues/4131))
* Disallow attribute/prop names from matching two-way-bound names or `{shorthand}` attribute/prop names ([#4325](https://github.com/sveltejs/svelte/issues/4325))
* Improve performance of `flush()` by not using `.shift()` ([#4356](https://github.com/sveltejs/svelte/pull/4356))
* Permit reserved keywords as destructuring keys in `{#each}` ([#4372](https://github.com/sveltejs/svelte/issues/4372))
* Disallow reserved keywords in `{expressions}` ([#4372](https://github.com/sveltejs/svelte/issues/4372))
* Fix code generation error with precedence of arrow functions ([#4384](https://github.com/sveltejs/svelte/issues/4384))
## 3.18.1

@ -141,7 +141,7 @@ export class Parser {
return result;
}
read_identifier() {
read_identifier(allow_reserved = false) {
const start = this.index;
let i = this.index;
@ -160,7 +160,7 @@ export class Parser {
const identifier = this.template.slice(this.index, this.index = i);
if (reserved.has(identifier)) {
if (!allow_reserved && reserved.has(identifier)) {
this.error({
code: `unexpected-reserved-word`,
message: `'${identifier}' is a reserved word in JavaScript and cannot be used here`

@ -1,4 +1,5 @@
import { Parser } from '../index';
import { reserved } from '../../utils/names';
interface Identifier {
start: number;
@ -116,8 +117,11 @@ export default function read_context(parser: Parser) {
break;
}
// TODO: DRY this out somehow
// We don't know whether we want to allow reserved words until we see whether there's a ':' after it
// Probably ideally we'd use Acorn to do all of this
const start = parser.index;
const name = parser.read_identifier();
const name = parser.read_identifier(true);
const key: Identifier = {
start,
end: parser.index,
@ -126,9 +130,19 @@ export default function read_context(parser: Parser) {
};
parser.allow_whitespace();
const value = parser.eat(':')
? (parser.allow_whitespace(), read_context(parser))
: key;
let value: Context;
if (parser.eat(':')) {
parser.allow_whitespace();
value = read_context(parser);
} else {
if (reserved.has(name)) {
parser.error({
code: `unexpected-reserved-word`,
message: `'${name}' is a reserved word in JavaScript and cannot be used here`
}, start);
}
value = key;
}
const property: Property = {
start,

@ -1,37 +1,9 @@
import { parse_expression_at } from '../acorn';
import { Parser } from '../index';
import { Identifier, Node, SimpleLiteral } from 'estree';
import { Node } from 'estree';
import { whitespace } from '../../utils/patterns';
const literals = new Map([['true', true], ['false', false], ['null', null]]);
export default function read_expression(parser: Parser): Node {
const start = parser.index;
const name = parser.read_until(/\s*}/);
if (name && /^[a-z]+$/.test(name)) {
const end = start + name.length;
if (literals.has(name)) {
return {
type: 'Literal',
start,
end,
value: literals.get(name),
raw: name,
} as SimpleLiteral;
}
return {
type: 'Identifier',
start,
end: start + name.length,
name,
} as Identifier;
}
parser.index = start;
try {
const node = parse_expression_at(parser.template, parser.index);

@ -20,6 +20,16 @@
"type": "Identifier",
"start": 20,
"end": 27,
"loc": {
"start": {
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 27
}
},
"name": "message"
}
}

@ -24,6 +24,16 @@
"type": "Identifier",
"start": 20,
"end": 28,
"loc": {
"start": {
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 28
}
},
"name": "readonly"
}
}

@ -1,37 +0,0 @@
{
"html": {
"start": 0,
"end": 25,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 25,
"type": "Element",
"name": "div",
"attributes": [
{
"start": 5,
"end": 18,
"type": "Attribute",
"name": "class",
"value": [
{
"start": 11,
"end": 18,
"type": "MustacheTag",
"expression": {
"type": "Identifier",
"start": 12,
"end": 17,
"name": "class"
}
}
]
}
],
"children": []
}
]
}
}

@ -31,6 +31,16 @@
"type": "Identifier",
"start": 20,
"end": 25,
"loc": {
"start": {
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 25
}
},
"name": "color"
}
},
@ -53,6 +63,16 @@
"type": "Identifier",
"start": 30,
"end": 35,
"loc": {
"start": {
"line": 1,
"column": 30
},
"end": {
"line": 1,
"column": 35
}
},
"name": "color"
}
}

@ -20,6 +20,16 @@
"type": "Identifier",
"start": 19,
"end": 22,
"loc": {
"start": {
"line": 1,
"column": 19
},
"end": {
"line": 1,
"column": 22
}
},
"name": "foo"
}
}

@ -27,6 +27,16 @@
"type": "Identifier",
"start": 50,
"end": 54,
"loc": {
"start": {
"line": 5,
"column": 19
},
"end": {
"line": 5,
"column": 23
}
},
"name": "name"
}
}

@ -40,6 +40,16 @@
"type": "Identifier",
"start": 46,
"end": 49,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 8
}
},
"name": "key"
}
},
@ -58,6 +68,16 @@
"type": "Identifier",
"start": 53,
"end": 58,
"loc": {
"start": {
"line": 2,
"column": 12
},
"end": {
"line": 2,
"column": 17
}
},
"name": "value"
}
}

@ -40,6 +40,16 @@
"type": "Identifier",
"start": 31,
"end": 37,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 11
}
},
"name": "animal"
}
}

@ -40,6 +40,16 @@
"type": "Identifier",
"start": 34,
"end": 35,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 6
}
},
"name": "i"
}
},
@ -58,6 +68,16 @@
"type": "Identifier",
"start": 39,
"end": 45,
"loc": {
"start": {
"line": 2,
"column": 10
},
"end": {
"line": 2,
"column": 16
}
},
"name": "animal"
}
}

@ -40,6 +40,16 @@
"type": "Identifier",
"start": 37,
"end": 41,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 9
}
},
"name": "todo"
}
}

@ -40,6 +40,16 @@
"type": "Identifier",
"start": 31,
"end": 37,
"loc": {
"start": {
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 11
}
},
"name": "animal"
}
}

@ -26,6 +26,16 @@
"type": "Identifier",
"start": 11,
"end": 15,
"loc": {
"start": {
"line": 1,
"column": 11
},
"end": {
"line": 1,
"column": 15
}
},
"name": "name"
}
},

@ -128,6 +128,16 @@
"type": "Identifier",
"start": 68,
"end": 75,
"loc": {
"start": {
"line": 3,
"column": 5
},
"end": {
"line": 3,
"column": 12
}
},
"name": "visible"
},
"children": [

@ -12,6 +12,16 @@
"type": "Identifier",
"start": 5,
"end": 8,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 8
}
},
"name": "foo"
},
"children": [

@ -12,6 +12,16 @@
"type": "Identifier",
"start": 5,
"end": 8,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 8
}
},
"name": "foo"
},
"children": [

@ -40,6 +40,16 @@
"type": "Literal",
"start": 18,
"end": 22,
"loc": {
"start": {
"line": 3,
"column": 6
},
"end": {
"line": 3,
"column": 10
}
},
"value": true,
"raw": "true"
},

@ -27,6 +27,16 @@
"type": "Identifier",
"start": 49,
"end": 52,
"loc": {
"start": {
"line": 5,
"column": 19
},
"end": {
"line": 5,
"column": 22
}
},
"name": "foo"
}
}

@ -33,6 +33,16 @@
"type": "Identifier",
"start": 90,
"end": 94,
"loc": {
"start": {
"line": 9,
"column": 11
},
"end": {
"line": 9,
"column": 15
}
},
"name": "name"
}
},

@ -33,6 +33,16 @@
"type": "Identifier",
"start": 79,
"end": 83,
"loc": {
"start": {
"line": 7,
"column": 11
},
"end": {
"line": 7,
"column": 15
}
},
"name": "name"
}
},

@ -33,6 +33,16 @@
"type": "Identifier",
"start": 52,
"end": 56,
"loc": {
"start": {
"line": 5,
"column": 11
},
"end": {
"line": 5,
"column": 15
}
},
"name": "name"
}
},

@ -26,6 +26,16 @@
"type": "Identifier",
"start": 5,
"end": 6,
"loc": {
"start": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 6
}
},
"name": "a"
}
},
@ -44,6 +54,16 @@
"type": "Identifier",
"start": 9,
"end": 10,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 10
}
},
"name": "b"
}
},
@ -62,6 +82,16 @@
"type": "Identifier",
"start": 15,
"end": 16,
"loc": {
"start": {
"line": 1,
"column": 15
},
"end": {
"line": 1,
"column": 16
}
},
"name": "c"
}
},

@ -18,6 +18,16 @@
"type": "Identifier",
"start": 9,
"end": 14,
"loc": {
"start": {
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 14
}
},
"name": "props"
}
}

@ -29,6 +29,16 @@
"type": "Identifier",
"start": 41,
"end": 44,
"loc": {
"start": {
"line": 2,
"column": 30
},
"end": {
"line": 2,
"column": 33
}
},
"name": "foo"
}
},

@ -33,6 +33,16 @@
"type": "Identifier",
"start": 19,
"end": 23,
"loc": {
"start": {
"line": 1,
"column": 19
},
"end": {
"line": 1,
"column": 23
}
},
"name": "name"
}
},

@ -1,20 +0,0 @@
{
"html": {
"start": 0,
"end": 7,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 7,
"type": "MustacheTag",
"expression": {
"type": "Identifier",
"start": 1,
"end": 6,
"name": "yield"
}
}
]
}
}

@ -0,0 +1,7 @@
<script>
const foo = [{ in: 'bar' }];
</script>
{#each foo as { in: bar }}
<p>{bar}</p>
{/each}

@ -0,0 +1,15 @@
[{
"code": "unexpected-reserved-word",
"message": "'case' is a reserved word in JavaScript and cannot be used here",
"start": {
"line": 1,
"column": 18,
"character": 18
},
"end": {
"line": 1,
"column": 18,
"character": 18
},
"pos": 18
}]
Loading…
Cancel
Save