handle wacky identifier names in templates

pull/1106/head
Rich Harris 7 years ago
parent 66b64e254d
commit a85b09ea97

@ -1,9 +1,11 @@
import { isIdentifierStart, isIdentifierChar } from 'acorn';
import { locate, Location } from 'locate-character';
import fragment from './state/fragment';
import { whitespace } from '../utils/patterns';
import { trimStart, trimEnd } from '../utils/trim';
import getCodeFrame from '../utils/getCodeFrame';
import reservedNames from '../utils/reservedNames';
import fullCharCodeAt from '../utils/fullCharCodeAt';
import hash from './utils/hash';
import { Node, Parsed } from '../interfaces';
import CompileError from '../utils/CompileError';
@ -147,7 +149,22 @@ export class Parser {
readIdentifier() {
const start = this.index;
const identifier = this.read(/[a-zA-Z_$][a-zA-Z0-9_$]*/);
let i = this.index;
const code = fullCharCodeAt(this.template, i);
if (!isIdentifierStart(code, true)) return null;
i += code <= 0xffff ? 1 : 2;
while (i < this.template.length) {
const code = fullCharCodeAt(this.template, i);
if (!isIdentifierChar(code, true)) break;
i += code <= 0xffff ? 1 : 2;
}
const identifier = this.template.slice(this.index, this.index = i);
if (reservedNames.has(identifier)) {
this.error(`'${identifier}' is a reserved word in JavaScript and cannot be used here`, start);

@ -0,0 +1,10 @@
// Adapted from https://github.com/acornjs/acorn/blob/6584815dca7440e00de841d1dad152302fdd7ca5/src/tokenize.js
// Reproduced under MIT License https://github.com/acornjs/acorn/blob/master/LICENSE
export default function fullCharCodeAt(str: string, i: number): number {
let code = str.charCodeAt(i)
if (code <= 0xd7ff || code >= 0xe000) return code;
let next = str.charCodeAt(i + 1);
return (code << 10) + next - 0x35fdc00;
}

@ -1,10 +1,14 @@
import { isIdentifierStart, isIdentifierChar } from 'acorn';
import fullCharCodeAt from './fullCharCodeAt';
export default function isValidIdentifier(str: string): boolean {
if (!isIdentifierStart(str.charCodeAt(0), true)) return false;
let i = 0;
for (let i = 0; i < str.length; i += 1) {
if (!isIdentifierChar(str.charCodeAt(i), true)) return false;
while (i < str.length) {
const code = fullCharCodeAt(str, i);
if (!(i === 0 ? isIdentifierStart : isIdentifierChar)(code, true)) return false;
i += code <= 0xffff ? 1 : 2;
}
return true;

@ -0,0 +1,3 @@
{{#each things as 𐊧}}
<p>𐊧</p>
{{/each}}

@ -0,0 +1,41 @@
{
"hash": 2991613308,
"html": {
"start": 0,
"end": 43,
"type": "Fragment",
"children": [
{
"start": 0,
"end": 43,
"type": "EachBlock",
"expression": {
"type": "Identifier",
"start": 8,
"end": 14,
"name": "things"
},
"children": [
{
"start": 24,
"end": 33,
"type": "Element",
"name": "p",
"attributes": [],
"children": [
{
"start": 27,
"end": 29,
"type": "Text",
"data": "𐊧"
}
]
}
],
"context": "𐊧"
}
]
},
"css": null,
"js": null
}
Loading…
Cancel
Save