fix handling of reserved keywords when parsing (#4390)

pull/4395/head
Conduitry 5 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)) * 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)) * 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)) * 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)) * Fix code generation error with precedence of arrow functions ([#4384](https://github.com/sveltejs/svelte/issues/4384))
## 3.18.1 ## 3.18.1

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

@ -1,4 +1,5 @@
import { Parser } from '../index'; import { Parser } from '../index';
import { reserved } from '../../utils/names';
interface Identifier { interface Identifier {
start: number; start: number;
@ -116,8 +117,11 @@ export default function read_context(parser: Parser) {
break; 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 start = parser.index;
const name = parser.read_identifier(); const name = parser.read_identifier(true);
const key: Identifier = { const key: Identifier = {
start, start,
end: parser.index, end: parser.index,
@ -126,9 +130,19 @@ export default function read_context(parser: Parser) {
}; };
parser.allow_whitespace(); parser.allow_whitespace();
const value = parser.eat(':') let value: Context;
? (parser.allow_whitespace(), read_context(parser)) if (parser.eat(':')) {
: key; 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 = { const property: Property = {
start, start,

@ -1,37 +1,9 @@
import { parse_expression_at } from '../acorn'; import { parse_expression_at } from '../acorn';
import { Parser } from '../index'; import { Parser } from '../index';
import { Identifier, Node, SimpleLiteral } from 'estree'; import { Node } from 'estree';
import { whitespace } from '../../utils/patterns'; import { whitespace } from '../../utils/patterns';
const literals = new Map([['true', true], ['false', false], ['null', null]]);
export default function read_expression(parser: Parser): Node { 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 { try {
const node = parse_expression_at(parser.template, parser.index); const node = parse_expression_at(parser.template, parser.index);

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

@ -24,6 +24,16 @@
"type": "Identifier", "type": "Identifier",
"start": 20, "start": 20,
"end": 28, "end": 28,
"loc": {
"start": {
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 28
}
},
"name": "readonly" "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", "type": "Identifier",
"start": 20, "start": 20,
"end": 25, "end": 25,
"loc": {
"start": {
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 25
}
},
"name": "color" "name": "color"
} }
}, },
@ -53,6 +63,16 @@
"type": "Identifier", "type": "Identifier",
"start": 30, "start": 30,
"end": 35, "end": 35,
"loc": {
"start": {
"line": 1,
"column": 30
},
"end": {
"line": 1,
"column": 35
}
},
"name": "color" "name": "color"
} }
} }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -33,6 +33,16 @@
"type": "Identifier", "type": "Identifier",
"start": 19, "start": 19,
"end": 23, "end": 23,
"loc": {
"start": {
"line": 1,
"column": 19
},
"end": {
"line": 1,
"column": 23
}
},
"name": "name" "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