Skip to content

Commit 11469ef

Browse files
committed
Merge branch 'master' of github.com:sveltejs/svelte
2 parents c45c7a9 + fa2f589 commit 11469ef

File tree

8 files changed

+119
-2
lines changed

8 files changed

+119
-2
lines changed

src/compile/nodes/Document.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Node from './shared/Node';
2+
import EventHandler from './EventHandler';
3+
4+
export default class Document extends Node {
5+
type: 'Document';
6+
handlers: EventHandler[];
7+
8+
constructor(component, parent, scope, info) {
9+
super(component, parent, scope, info);
10+
11+
this.handlers = [];
12+
13+
info.attributes.forEach(node => {
14+
if (node.type === 'EventHandler') {
15+
this.handlers.push(new EventHandler(component, this, scope, node));
16+
}
17+
18+
else {
19+
// TODO there shouldn't be anything else here...
20+
}
21+
});
22+
}
23+
}

src/compile/nodes/shared/mapChildren.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import AwaitBlock from '../AwaitBlock';
22
import Comment from '../Comment';
3+
import Document from '../Document';
34
import EachBlock from '../EachBlock';
45
import Element from '../Element';
56
import Head from '../Head';
@@ -18,6 +19,7 @@ function getConstructor(type): typeof Node {
1819
switch (type) {
1920
case 'AwaitBlock': return AwaitBlock;
2021
case 'Comment': return Comment;
22+
case 'Document': return Document;
2123
case 'EachBlock': return EachBlock;
2224
case 'Element': return Element;
2325
case 'Head': return Head;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import Renderer from '../Renderer';
2+
import Block from '../Block';
3+
import Node from '../../nodes/shared/Node';
4+
import Wrapper from './shared/Wrapper';
5+
import deindent from '../../../utils/deindent';
6+
import Document from '../../nodes/Document';
7+
8+
export default class DocumentWrapper extends Wrapper {
9+
node: Document;
10+
11+
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: Node) {
12+
super(renderer, block, parent, node);
13+
}
14+
15+
render(block: Block, parentNode: string, parentNodes: string) {
16+
const { renderer } = this;
17+
const { component } = renderer;
18+
19+
this.node.handlers.forEach(handler => {
20+
// TODO verify that it's a valid callee (i.e. built-in or declared method)
21+
component.addSourcemapLocations(handler.expression);
22+
23+
const isCustomEvent = component.events.has(handler.name);
24+
25+
let usesState = handler.dependencies.size > 0;
26+
27+
handler.render(component, block, 'document', false); // TODO hoist?
28+
29+
const handlerName = block.getUniqueName(`onwindow${handler.name}`);
30+
const handlerBody = deindent`
31+
${usesState && `var ctx = #component.get();`}
32+
${handler.snippet};
33+
`;
34+
35+
if (isCustomEvent) {
36+
// TODO dry this out
37+
block.addVariable(handlerName);
38+
39+
block.builders.hydrate.addBlock(deindent`
40+
${handlerName} = %events-${handler.name}.call(#component, document, function(event) {
41+
${handlerBody}
42+
});
43+
`);
44+
45+
block.builders.destroy.addLine(deindent`
46+
${handlerName}.destroy();
47+
`);
48+
} else {
49+
block.builders.init.addBlock(deindent`
50+
function ${handlerName}(event) {
51+
${handlerBody}
52+
}
53+
document.addEventListener("${handler.name}", ${handlerName});
54+
`);
55+
56+
block.builders.destroy.addBlock(deindent`
57+
document.removeEventListener("${handler.name}", ${handlerName});
58+
`);
59+
}
60+
});
61+
}
62+
}

src/compile/render-dom/wrappers/Fragment.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Wrapper from './shared/Wrapper';
22
import AwaitBlock from './AwaitBlock';
33
import DebugTag from './DebugTag';
4+
import Document from './Document';
45
import EachBlock from './EachBlock';
56
import Element from './Element';
67
import Head from './Head';
@@ -21,6 +22,7 @@ import Block from '../Block';
2122
const wrappers = {
2223
AwaitBlock,
2324
Comment: null,
25+
Document,
2426
DebugTag,
2527
EachBlock,
2628
Element,

src/compile/render-ssr/Renderer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const handlers: Record<string, Handler> = {
2121
AwaitBlock,
2222
Comment,
2323
DebugTag,
24+
Document: noop,
2425
EachBlock,
2526
Element,
2627
Head,

src/parse/state/tag.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { Node } from '../../interfaces';
1111
const validTagName = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/;
1212

1313
const metaTags = new Map([
14+
['svelte:document', 'Document'],
1415
['svelte:window', 'Window'],
1516
['svelte:head', 'Head']
1617
]);
@@ -96,9 +97,12 @@ export default function tag(parser: Parser) {
9697
if (metaTags.has(name)) {
9798
const slug = metaTags.get(name).toLowerCase();
9899
if (isClosingTag) {
99-
if (name === 'svelte:window' && parser.current().children.length) {
100+
if (
101+
(name === 'svelte:window' || name === 'svelte:document') &&
102+
parser.current().children.length
103+
) {
100104
parser.error({
101-
code: `invalid-window-content`,
105+
code: `invalid-${name.slice(7)}-content`,
102106
message: `<${name}> cannot have children`
103107
}, parser.current().children[0].start);
104108
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export default {
2+
test(assert, component, target, window) {
3+
assert.equal(component.get().events.toString(), '');
4+
const event1 = new window.Event('mouseenter');
5+
window.document.dispatchEvent(event1);
6+
assert.equal(component.get().events.toString(), 'enter');
7+
const event2 = new window.Event('mouseleave');
8+
window.document.dispatchEvent(event2);
9+
assert.equal(component.get().events.toString(), 'enter,leave');
10+
},
11+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<svelte:document on:mouseenter='log("enter")' on:mouseleave='log("leave")'/>
2+
3+
<script>
4+
export default {
5+
data: () => ({ events: [] }),
6+
methods: {
7+
log(event) {
8+
this.set({ events: this.get().events.concat(event) });
9+
},
10+
},
11+
};
12+
</script>

0 commit comments

Comments
 (0)