check that event handler callee corresponds to a valid method

pull/473/head
Rich Harris 8 years ago
parent 3595470305
commit c7ac8b82ba

@ -1,7 +1,13 @@
import * as namespaces from '../../utils/namespaces.js';
import flattenReference from '../../utils/flattenReference.js';
const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|switch|symbol|text|textPath|title|tref|tspan|unknown|use|view|vkern)$/;
function list ( items, conjunction = 'or' ) {
if ( items.length === 1 ) return items[0];
return `${items.slice( 0, -1 ).join( ', ' )} ${conjunction} ${items[ items.length - 1 ]}`;
}
export default function validateHtml ( validator, html ) {
let elementDepth = 0;
@ -12,6 +18,30 @@ export default function validateHtml ( validator, html ) {
}
elementDepth += 1;
node.attributes.forEach( attribute => {
if ( attribute.type === 'EventHandler' ) {
const { callee, start, type } = attribute.expression;
if ( type !== 'CallExpression' ) {
validator.error( `Expected a call expression`, start );
}
const { name } = flattenReference( callee );
if ( name === 'this' || name === 'event' ) return;
if ( callee.type === 'Identifier' && callee.name === 'set' || callee.name === 'fire' || callee.name in validator.methods ) return;
const validCallees = list( [ 'this.*', 'event.*', 'set', 'fire' ].concat( Object.keys( validator.methods ) ) );
let message = `'${validator.source.slice( callee.start, callee.end )}' is an invalid callee (should be one of ${validCallees})`;
if ( callee.type === 'Identifier' && callee.name in validator.helpers ) {
message += `. '${callee.name}' exists on 'helpers', did you put it in the wrong place?`;
}
validator.error( message, start );
}
});
}
if ( node.children ) {

@ -36,9 +36,13 @@ export default function validate ( parsed, source, { onerror, onwarn, name, file
});
},
source,
namespace: null,
defaultExport: null,
properties: {}
properties: {},
methods: {},
helpers: {}
};
if ( name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test( name ) ) {

@ -72,4 +72,12 @@ export default function validateJs ( validator, js ) {
});
}
});
[ 'methods', 'helpers' ].forEach( key => {
if ( validator.properties[ key ] ) {
validator.properties[ key ].value.properties.forEach( prop => {
validator[ key ][ prop.key.name ] = prop.value;
});
}
});
}

@ -0,0 +1,8 @@
[{
"message": "'foo' is an invalid callee (should be one of this.*, event.*, set, fire or bar). 'foo' exists on 'helpers', did you put it in the wrong place?",
"pos": 18,
"loc": {
"line": 1,
"column": 18
}
}]

@ -0,0 +1,17 @@
<button on:click='foo()'></button>
<script>
export default {
methods: {
bar () {
// ...
}
},
helpers: {
foo ( x ) {
return x;
}
}
};
</script>

@ -0,0 +1,8 @@
[{
"message": "'foo' is an invalid callee (should be one of this.*, event.*, set, fire or bar)",
"pos": 18,
"loc": {
"line": 1,
"column": 18
}
}]

@ -0,0 +1,11 @@
<button on:click='foo()'></button>
<script>
export default {
methods: {
bar () {
// ...
}
}
};
</script>
Loading…
Cancel
Save