Merge pull request #2743 from sveltejs/namespaced-components

implement namespaced components
pull/2749/head
Rich Harris 6 years ago committed by GitHub
commit 68d7dca1c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,7 +7,7 @@ title: Template syntax
--- ---
A lowercase tag, like `<div>`, denotes a regular HTML element. A capitalised tag, such as `<Widget>`, indicates a *component*. A lowercase tag, like `<div>`, denotes a regular HTML element. A capitalised tag, such as `<Widget>` or `<Namespace.Widget>`, indicates a *component*.
```html ```html
<script> <script>

@ -759,7 +759,7 @@ export default class Component {
const { name } = object; const { name } = object;
if (name[0] === '$' && !scope.has(name)) { if (name[0] === '$' && !scope.has(name)) {
component.warn_if_undefined(object, null); component.warn_if_undefined(name, object, null);
} }
} }
}, },
@ -1202,9 +1202,7 @@ export default class Component {
return `ctx.${name}`; return `ctx.${name}`;
} }
warn_if_undefined(node, template_scope: TemplateScope) { warn_if_undefined(name: string, node, template_scope: TemplateScope) {
let { name } = node;
if (name[0] === '$') { if (name[0] === '$') {
name = name.slice(1); name = name.slice(1);
this.has_reactive_assignments = true; // TODO does this belong here? this.has_reactive_assignments = true; // TODO does this belong here?

@ -11,7 +11,7 @@ export default class Action extends Node {
constructor(component: Component, parent, scope, info) { constructor(component: Component, parent, scope, info) {
super(component, parent, scope, info); super(component, parent, scope, info);
component.warn_if_undefined(info, scope); component.warn_if_undefined(info.name, info, scope);
this.name = info.name; this.name = info.name;
component.qualify(info.name); component.qualify(info.name);

@ -10,7 +10,7 @@ export default class Animation extends Node {
constructor(component: Component, parent, scope, info) { constructor(component: Component, parent, scope, info) {
super(component, parent, scope, info); super(component, parent, scope, info);
component.warn_if_undefined(info, scope); component.warn_if_undefined(info.name, info, scope);
this.name = info.name; this.name = info.name;
component.qualify(info.name); component.qualify(info.name);

@ -23,8 +23,9 @@ export default class InlineComponent extends Node {
super(component, parent, scope, info); super(component, parent, scope, info);
if (info.name !== 'svelte:component' && info.name !== 'svelte:self') { if (info.name !== 'svelte:component' && info.name !== 'svelte:self') {
component.warn_if_undefined(info, scope); const name = info.name.split('.')[0]; // accommodate namespaces
component.add_reference(info.name); component.warn_if_undefined(name, info, scope);
component.add_reference(name);
} }
this.name = info.name; this.name = info.name;

@ -12,7 +12,7 @@ export default class Transition extends Node {
constructor(component: Component, parent, scope, info) { constructor(component: Component, parent, scope, info) {
super(component, parent, scope, info); super(component, parent, scope, info);
component.warn_if_undefined(info, scope); component.warn_if_undefined(info.name, info, scope);
this.name = info.name; this.name = info.name;
component.qualify(info.name); component.qualify(info.name);

@ -149,7 +149,7 @@ export default class Expression {
} }
component.add_reference(name); component.add_reference(name);
component.warn_if_undefined(nodes[0], template_scope); component.warn_if_undefined(name, nodes[0], template_scope);
} }
this.skip(); this.skip();

@ -63,7 +63,7 @@ export default class InlineComponentWrapper extends Wrapper {
this.var = ( this.var = (
this.node.name === 'svelte:self' ? renderer.component.name : this.node.name === 'svelte:self' ? renderer.component.name :
this.node.name === 'svelte:component' ? 'switch_instance' : this.node.name === 'svelte:component' ? 'switch_instance' :
this.node.name sanitize(this.node.name)
).toLowerCase(); ).toLowerCase();
if (this.node.children.length) { if (this.node.children.length) {

@ -75,7 +75,7 @@ describe("runtime", () => {
compileOptions.accessors = 'accessors' in config ? config.accessors : true; compileOptions.accessors = 'accessors' in config ? config.accessors : true;
Object.keys(require.cache) Object.keys(require.cache)
.filter(x => x.endsWith(".svelte")) .filter(x => x.endsWith('.svelte'))
.forEach(file => { .forEach(file => {
delete require.cache[file]; delete require.cache[file];
}); });

@ -0,0 +1,5 @@
<script>
export let foo;
</script>
<p>foo {foo}</p>

@ -0,0 +1,22 @@
import * as path from 'path';
export default {
props: {
a: 1
},
html: `
<p>foo 1</p>
`,
before_test() {
delete require.cache[path.resolve(__dirname, 'components.js')];
},
test({ assert, component, target }) {
component.a = 2;
assert.htmlEqual(target.innerHTML, `
<p>foo 2</p>
`);
}
};

@ -0,0 +1,3 @@
import Foo from './Foo.svelte';
export default { Foo };

@ -0,0 +1,7 @@
<script>
import Components from './components.js';
export let a;
</script>
<Components.Foo foo={a}/>

@ -96,10 +96,11 @@ describe("ssr", () => {
(config.skip ? it.skip : config.solo ? it.only : it)(dir, () => { (config.skip ? it.skip : config.solo ? it.only : it)(dir, () => {
const cwd = path.resolve("test/runtime/samples", dir); const cwd = path.resolve("test/runtime/samples", dir);
glob('**/*.svelte', { cwd: `test/runtime/samples/${dir}` }).forEach(file => { Object.keys(require.cache)
const resolved = require.resolve(`../runtime/samples/${dir}/${file}`); .filter(x => x.endsWith('.svelte'))
delete require.cache[resolved]; .forEach(file => {
}); delete require.cache[file];
});
const compileOptions = Object.assign({ sveltePath }, config.compileOptions, { const compileOptions = Object.assign({ sveltePath }, config.compileOptions, {
generate: 'ssr' generate: 'ssr'

@ -0,0 +1,5 @@
<script>
import * as NS from 'some-library';
</script>
<NS.Foo/>

@ -0,0 +1,16 @@
export default {
test(assert, vars) {
assert.deepEqual(vars, [
{
name: 'NS',
export_name: null,
injected: false,
module: false,
mutated: false,
reassigned: false,
referenced: true,
writable: false
}
]);
}
};

@ -0,0 +1,5 @@
<script>
import * as NS from 'some-library';
</script>
<NS.Foo/>
Loading…
Cancel
Save