more validation tests

pull/1866/head
Rich Harris 7 years ago
parent 75bb357e98
commit f35edafad3

@ -17,6 +17,7 @@ import getCodeFrame from '../utils/getCodeFrame';
import flattenReference from '../utils/flattenReference';
import addToSet from '../utils/addToSet';
import isReference from 'is-reference';
import TemplateScope from './nodes/shared/TemplateScope';
type Meta = {
namespace?: string;
@ -53,7 +54,8 @@ export default class Component {
options: CompileOptions;
fragment: Fragment;
module_scope: Scope;
module_scope_map: WeakMap<Node, Scope>;
instance_scope: Scope;
instance_scope_map: WeakMap<Node, Scope>;
meta: Meta;
@ -391,8 +393,8 @@ export default class Component {
return dependencies;
}
let { module_scope, module_scope_map: map } = this;
let scope = module_scope;
let { instance_scope, instance_scope_map: map } = this;
let scope = instance_scope;
const component = this;
let bail = false;
@ -405,7 +407,7 @@ export default class Component {
if (isReference(node, parent)) {
const { name } = flattenReference(node);
if (scope.findOwner(name) === module_scope) {
if (scope.findOwner(name) === instance_scope) {
dependencies.add(name);
}
}
@ -502,6 +504,9 @@ export default class Component {
this.addSourcemapLocations(script.content);
let { scope } = createScopes(script.content);
this.module_scope = scope;
// TODO unindent
this.extract_imports_and_exports(script.content, this.imports, this.module_exports);
@ -515,8 +520,8 @@ export default class Component {
this.addSourcemapLocations(script.content);
let { scope, map, globals } = createScopes(script.content);
this.module_scope = scope;
this.module_scope_map = map;
this.instance_scope = scope;
this.instance_scope_map = map;
scope.declarations.forEach((node, name) => {
this.userVars.add(name);
@ -561,6 +566,18 @@ export default class Component {
this.javascript = this.extract_javascript(script);
}
warn_if_undefined(node, template_scope: TemplateScope) {
const { name } = node;
if (this.module_scope && this.module_scope.declarations.has(name)) return;
if (this.instance_scope && this.instance_scope.declarations.has(name)) return;
if (template_scope.names.has(name)) return;
this.warn(node, {
code: 'missing-declaration',
message: `'${name}' is not defined`
});
}
instrument(node, parent, name, is_event_handler) {
// TODO only make values reactive if they're used
// in the template

@ -1,5 +1,6 @@
import Node from './shared/Node';
import Expression from './shared/Expression';
import Component from '../Component';
export default class Action extends Node {
type: 'Action';
@ -7,9 +8,11 @@ export default class Action extends Node {
expression: Expression;
usesContext: boolean;
constructor(component, parent, scope, info) {
constructor(component: Component, parent, scope, info) {
super(component, parent, scope, info);
component.warn_if_undefined(info, scope);
this.name = info.name;
this.expression = info.expression

@ -9,6 +9,8 @@ export default class Animation extends Node {
constructor(component, parent, scope, info) {
super(component, parent, scope, info);
component.warn_if_undefined(info, scope);
this.name = info.name;
if (parent.animation) {

@ -20,6 +20,8 @@ export default class InlineComponent extends Node {
constructor(component: Component, parent, scope, info) {
super(component, parent, scope, info);
component.warn_if_undefined(info, scope);
component.hasComponents = true;
this.name = info.name;

@ -1,5 +1,6 @@
import Node from './shared/Node';
import Expression from './shared/Expression';
import Component from '../Component';
export default class Transition extends Node {
type: 'Transition';
@ -7,9 +8,11 @@ export default class Transition extends Node {
directive: string;
expression: Expression;
constructor(component, parent, scope, info) {
constructor(component: Component, parent, scope, info) {
super(component, parent, scope, info);
component.warn_if_undefined(info, scope);
this.name = info.name;
this.directive = info.intro && info.outro ? 'transition' : info.intro ? 'in' : 'out';

@ -10,7 +10,11 @@ export function createScopes(expression: Node) {
walk(expression, {
enter(node: Node, parent: Node) {
if (/Function/.test(node.type)) {
if (node.type === 'ImportDeclaration') {
node.specifiers.forEach(specifier => {
scope.declarations.set(specifier.local.name, specifier);
});
} else if (/Function/.test(node.type)) {
if (node.type === 'FunctionDeclaration') {
scope.declarations.set(node.id.name, node);
scope = new Scope(scope, false);

@ -1,3 +1,7 @@
<script>
import Widget from './Widget.html';
</script>
<Widget scope="foo">
<input autofocus>
</Widget>

@ -4,14 +4,14 @@
"message": "A11y: Avoid using autofocus",
"start": {
"column": 8,
"line": 2,
"character": 29
"line": 6,
"character": 86
},
"end": {
"line": 2,
"line": 6,
"column": 17,
"character": 38
"character": 95
},
"pos": 29
"pos": 86
}
]

@ -1,6 +1,6 @@
[{
"code": "missing-action",
"message": "Missing action 'whatever'",
"code": "missing-declaration",
"message": "'whatever' is not defined",
"pos": 5,
"start": {
"line": 1,

@ -1,6 +1,6 @@
[{
"code": "missing-animation",
"message": "Missing animation 'foo'",
"code": "missing-declaration",
"message": "'foo' is not defined",
"start": {
"line": 2,
"column": 6,

@ -1,6 +1,6 @@
[{
"code": "missing-component",
"message": "Widget component is not defined",
"code": "missing-declaration",
"message": "'Widget' is not defined",
"start": {
"line": 2,
"column": 1,

@ -1,6 +1,6 @@
[{
"code": "missing-transition",
"message": "Missing transition 'foo'",
"code": "missing-declaration",
"message": "'foo' is not defined",
"start": {
"line": 1,
"column": 5,
Loading…
Cancel
Save