Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement namespaced components #2743

Merged
merged 5 commits into from
May 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion site/content/docs/02-template-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
<script>
Expand Down
6 changes: 2 additions & 4 deletions src/compile/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ export default class Component {
const { name } = object;

if (name[0] === '$' && !scope.has(name)) {
component.warn_if_undefined(object, null);
component.warn_if_undefined(name, object, null);
}
}
},
Expand Down Expand Up @@ -1202,9 +1202,7 @@ export default class Component {
return `ctx.${name}`;
}

warn_if_undefined(node, template_scope: TemplateScope) {
let { name } = node;

warn_if_undefined(name: string, node, template_scope: TemplateScope) {
if (name[0] === '$') {
name = name.slice(1);
this.has_reactive_assignments = true; // TODO does this belong here?
Expand Down
2 changes: 1 addition & 1 deletion src/compile/nodes/Action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default class Action extends Node {
constructor(component: 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;
component.qualify(info.name);
Expand Down
2 changes: 1 addition & 1 deletion src/compile/nodes/Animation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default class Animation extends Node {
constructor(component: 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;
component.qualify(info.name);
Expand Down
5 changes: 3 additions & 2 deletions src/compile/nodes/InlineComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ export default class InlineComponent extends Node {
super(component, parent, scope, info);

if (info.name !== 'svelte:component' && info.name !== 'svelte:self') {
component.warn_if_undefined(info, scope);
component.add_reference(info.name);
const name = info.name.split('.')[0]; // accommodate namespaces
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did it not seem safe to just roll this logic into warn_if_undefined itself instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh, I guess you need to add_reference here with it anyway. It might be nice though if warn_if_undefined didn't require an extra name arg as well as the info arg.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's silly to let this hold up the PR actually, gonna go ahead an approve

component.warn_if_undefined(name, info, scope);
component.add_reference(name);
}

this.name = info.name;
Expand Down
2 changes: 1 addition & 1 deletion src/compile/nodes/Transition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default class Transition extends Node {
constructor(component: 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;
component.qualify(info.name);
Expand Down
2 changes: 1 addition & 1 deletion src/compile/nodes/shared/Expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export default class Expression {
}

component.add_reference(name);
component.warn_if_undefined(nodes[0], template_scope);
component.warn_if_undefined(name, nodes[0], template_scope);
}

this.skip();
Expand Down
2 changes: 1 addition & 1 deletion src/compile/render-dom/wrappers/InlineComponent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export default class InlineComponentWrapper extends Wrapper {
this.var = (
this.node.name === 'svelte:self' ? renderer.component.name :
this.node.name === 'svelte:component' ? 'switch_instance' :
this.node.name
sanitize(this.node.name)
).toLowerCase();

if (this.node.children.length) {
Expand Down
2 changes: 1 addition & 1 deletion test/runtime/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ describe("runtime", () => {
compileOptions.accessors = 'accessors' in config ? config.accessors : true;

Object.keys(require.cache)
.filter(x => x.endsWith(".svelte"))
.filter(x => x.endsWith('.svelte'))
.forEach(file => {
delete require.cache[file];
});
Expand Down
5 changes: 5 additions & 0 deletions test/runtime/samples/component-namespaced/Foo.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
export let foo;
</script>

<p>foo {foo}</p>
22 changes: 22 additions & 0 deletions test/runtime/samples/component-namespaced/_config.js
Original file line number Diff line number Diff line change
@@ -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>
`);
}
};
3 changes: 3 additions & 0 deletions test/runtime/samples/component-namespaced/components.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Foo from './Foo.svelte';

export default { Foo };
7 changes: 7 additions & 0 deletions test/runtime/samples/component-namespaced/main.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script>
import Components from './components.js';

export let a;
</script>

<Components.Foo foo={a}/>
9 changes: 5 additions & 4 deletions test/server-side-rendering/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,11 @@ describe("ssr", () => {
(config.skip ? it.skip : config.solo ? it.only : it)(dir, () => {
const cwd = path.resolve("test/runtime/samples", dir);

glob('**/*.svelte', { cwd: `test/runtime/samples/${dir}` }).forEach(file => {
const resolved = require.resolve(`../runtime/samples/${dir}/${file}`);
delete require.cache[resolved];
});
Object.keys(require.cache)
.filter(x => x.endsWith('.svelte'))
.forEach(file => {
delete require.cache[file];
});

const compileOptions = Object.assign({ sveltePath }, config.compileOptions, {
generate: 'ssr'
Expand Down
5 changes: 5 additions & 0 deletions test/validator/samples/component-namespaced/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
import * as NS from 'some-library';
</script>

<NS.Foo/>
1 change: 1 addition & 0 deletions test/validator/samples/component-namespaced/warnings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
16 changes: 16 additions & 0 deletions test/vars/samples/component-namespaced/_config.js
Original file line number Diff line number Diff line change
@@ -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
}
]);
}
};
5 changes: 5 additions & 0 deletions test/vars/samples/component-namespaced/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
import * as NS from 'some-library';
</script>

<NS.Foo/>